Perl中的面向对象编程并不是一开始就存在——最初这个语言是过程式的。OOP的加入是通过基于哈希和包的动态结构实现的。Perl并没有像大多数其他语言那样使用内置的class关键字,而是操作包和引用的bless。
Perl OOP的第一个版本就是一个导出的函数包和数据结构(通常是哈希),通过bless函数将该结构与包的归属挂钩。后来出现了CPAN模块,如Moose/Mouse/Moo,实现了功能齐全的元OOP(元类、属性、角色)。
缺乏统一的OOP模式导致了风格的多样性以及项目间OOP代码的不兼容。由于语言的动态特性,可能会出现错误(例如命名错误、早绑定/晚绑定、手动操作bless方法)。
代码示例:
package Animal; sub new { my ($class, %args) = @_; bless { %args }, $class; } sub speak { my $self = shift; print "动物在说 "; } package Cat; our @ISA = ('Animal'); sub speak { my $self = shift; print "猫在喵喵 "; } my $cat = Cat->new(name => 'Barsik'); $cat->speak; # 猫在喵喵
关键特性:
如果在new中返回一个未bless的引用而只是一个哈希,会发生什么?
返回未bless的引用将导致后续的通过->$obj调用的方法失去与包的联系,找不到所需的方法——将发生致命错误。
Perl如何实现多重继承和冲突方法的解决?
Perl支持多重继承——@ISA数组中可以有多个包。方法搜索是宽度优先、从左到右,遍历所有父类。在发生冲突时,将取第一个找到的方法。
可以在运行时"重新bless"(re-bless)对象吗,这意味着什么?
可以,通过bless可以在执行过程中更改对象对另一个包的归属。这可以用来改变对象的"类型"。但是,这样做的风险在于对象的内部内容可能与新的方法不匹配。
示例:
bless $cat, 'Dog'; # 现在$cat表现得像一只狗!
在项目中通过显然未初始化的数组创建对象,而方法期望的是哈希引用。程序在调用任何方法时崩溃,尽管Perl的语法允许对任意内容进行bless。
优点:
缺点:
使用Moose和可验证的构造函数,严格类型化属性,自动生成访问方法,对象之间的关系简洁描述。
优点:
缺点: