Chinaunix首页 | 论坛 | 博客
  • 博客访问: 150223
  • 博文数量: 52
  • 博客积分: 1410
  • 博客等级: 上尉
  • 技术积分: 490
  • 用 户 组: 普通用户
  • 注册时间: 2007-11-05 12:05
文章分类

全部博文(52)

文章存档

2013年(1)

2010年(3)

2009年(6)

2008年(25)

2007年(17)

我的朋友

分类:

2010-02-12 21:25:53

1       对象

一个对象只不过是一个引用,一个类只是一个包,一个方法只是一个子过程

 

1.1    bless

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

请按任意键继续. . .

 

1.2    new

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 ,静态调用方法是用双冒号不是箭头。

 

2       继承

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 => 'Africa',name=>$name};

    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

Africa

my name is Africa and come from Africa

1

请按任意键继续. . .

 

3       重写

Perl里的重载是,是对符号的一些重载overloading,据说和C++类似,挺复杂的一个东西,现在也了解不到他有什么用处。 所以可能用到的还是重写overriding, 就是在继承父类的时候把父类的方法用同样的名字覆盖了,做不同的事情。在设计PERL程序成多态的时候有用。

 

4       多态

简单的说在运行时动态的选择正确的类方法就是多态。 假如你设计了一个父类,继承他的子类实现了这个类具体的方法(用重写)。 然后你提供给别人一个接口,别人可以不用关注这个对象具体是哪个类而直接调用你提供的接口。下面就是多态的一个例子。 在更复杂的编程时多态通常结合一些设计模式来实现。

 

本例来自

Cat Dog继承Animalnew方法。并且都有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!请按任意键继续. . .

 

阅读(2741) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~