分类:
2010-02-12 21:25:53
一个对象只不过是一个引用,一个类只是一个包,一个方法只是一个子过程
bless是用来构造对象的, 通过bless把一个引用和这个类名相关联,返回这个引用就构造出一个对象。
事实上当你用ref去看这个引用的时候,它不是原来的HASH,而是这个类的对象。
如果没有bless 过那他的“类型”是不会变的。这就是bless的作用。
#!/usr/bin/perl
package TBLESS;
sub new(){
my $class = shift;
my $this = { 'name'=>'ivan' };
my $thash = {};
bless $this, $class;
print ref($this)."\n";
print ref($thash)."\n";
}
package main;
my $b = new TBLESS();
#output
TBLESS
HASH
请按任意键继续. . .
new 函数没什么特别,可以用任何其他更有意义的名字, 只不过每次在调用的时候,他的第一个隐藏的参数正好是这个类的名称。所以my $class = shift; 这里的$this也不像其他面向对象里的特殊意思。 只是用它在这里比较贴切。 CU上的一段解释是很合理的。
--------
面向对象的实现实际上只是对箭头操作符->的重载.
当->左边是个裸字符串的时候, 比如DBI->new(); 就会被转化成 DBI::new('DBI');的调用.
当->左边是个被bless过的结构时, 比如$db = {}; bless $db, DBI; $db->connect($host, $port); 就会被转化成DBI::connect($db, $host, $port);
不过PERL解释器还要考虑继承的问题,即@ISA数组。如果要传参数到new函数的话,同样是被放到@_数组里, 所以只要对除了隐藏的参数(my $class = shift;)shift过后再进行处理。但是如果用静态的调用方法就不用shift 了 ,静态调用方法是用双冒号不是箭头。
Perl 里继承也没有什么特殊语法,只不过通过一个@ISA数组,这个数组里面包含其他包(类)的名字。 多继承就是这个@ISA数组包含多个类(包)名字。 当他在当前对象所属的包找不到想要方法的时候就向@ISA数组里的另外的包里搜索,而且如果编译器会处理 搜索到的包(@ISA数组元素的里包 )的@ISA数组。
所以通过@ISA只能继承方法,不能继承数据。下面的例子说明简单的继承数据habitat的方法,和调用父类talk()方法。
package Animal;
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(talk);
sub new(){
my ($class,$name) = @_;
$this = {habitat => '
bless $this,$class;
}
sub talk(){
$class = shift;
print "my name is $this->{'habitat'} and come from $this->{'habitat'}\n";
}
package Cat;
use Animal;
require Exporter;
@ISA = qw(Animal);
sub new(){
my ($class,$name) = @_;
my $this = $class->SUPER::new();
#my $this = Animal->new("milk");
$this->{'name'} = $name;
bless $this,$class;
}
package main;
$cat = new Cat("missy");
print $cat->{'name'}."\n";
print $cat->{'habitat'}."\n";
print $cat->talk()."\n";
将输出:
missy
my name is Africa and come from
1
请按任意键继续. . .
Perl里的重载是,是对符号的一些重载overloading,据说和C++类似,挺复杂的一个东西,现在也了解不到他有什么用处。 所以可能用到的还是重写overriding, 就是在继承父类的时候把父类的方法用同样的名字覆盖了,做不同的事情。在设计PERL程序成多态的时候有用。
简单的说在运行时动态的选择正确的类方法就是多态。 假如你设计了一个父类,继承他的子类实现了这个类具体的方法(用重写)。 然后你提供给别人一个接口,别人可以不用关注这个对象具体是哪个类而直接调用你提供的接口。下面就是多态的一个例子。 在更复杂的编程时多态通常结合一些设计模式来实现。
本例来自
Cat 和Dog继承Animal的new方法。并且都有talk方法。 在主程序中
for my $animal ( $a, $b, $c ) {
print $animal->{name} . ': ' . $animal->talk;
}
编译器会区分$animal 具体是哪个对象,然后再来调用他的talk方法来实现正确的功能.
#!/usr/bin/perl
{
package Animal;
sub new {
my ( $class, $name ) = @_;
bless { name => $name }, $class;
}
}
{
package Cat;
use base qw(Animal);
sub talk { 'Meow' }
}
{
package Dog;
use base qw(Animal);
sub talk { 'Woof! Woof!' }
}
my $a = Cat->new('Missy');
my $b = Cat->new('Mr. Mistoffelees');
my $c = Dog->new('Lassie');
for my $animal ( $a, $b, $c ) {
print $animal->{name} . ': ' . $animal->talk;
}
将输出
Missy: MeowMr. Mistoffelees: MeowLassie: Woof! Woof!请按任意键继续. . .