Perl是一种动态语言,支持基于哈希和包的原型OOP。通常使用bless来创建对象:
package Animal; sub new { my ($class, %args) = @_; return bless { %args }, $class; } sub speak { print "一个动物发出声音 "; } package Dog; use parent 'Animal'; # 或者our @ISA = ('Animal') sub speak { print "汪! "; } my $dog = Dog->new(name => 'Rex'); $dog->speak; # 输出: 汪!
这里构造函数new创建一个包含对象数据的哈希,并将其与类关联。方法被声明为普通子程序。可以通过@ISA或模块parent/base实现继承。Perl中的OOP灵活但不严格,这既带来了额外的可能性,也增加了细微之处。
在Perl中考虑到缺乏private/protected语法,如何更好地实现对象的私有属性/方法?
答案: 没有内置机制,但是可以通过包外的词法变量或命名约定(_private)来实现私有性。例如:
package Car; my $secret = 'hidden'; # 对包私有 sub _private { ... } # 协议:不要在外部调用
这种方法无法阻止访问,但被视为标准。
故事
在一个项目中定义了一个对象,包含指向其他对象的引用数组。开发人员忘记以$obj->method调用方法,而是以method($obj)调用,这导致了意外结果,尤其是在继承和方法重写时——错误地确定了类,并调用了父方法而不是子方法。
故事
使用包变量而不是词法变量来存储对象的状态导致一个状态的变化反映在所有类实例中,因为数据是共享的,而不是对象的个体数据。
故事
在动态加载类的大型项目中,对@ISA变量的隐式使用进行继承会导致父类列表未及时更新,程序意外失去方法或获得不正确的层次结构。