ChinaUnix首页 > 精华文章 > Perl > 正文

[精彩] 如何生成虚方法


http://www.chinaunix.net 作者:guweichen  发表于:2005-08-19 10:25:57
发表评论】 【查看原文】 【Perl讨论区】【关闭

小弟想在perl的Person Object中生成abstract method,  即
sub save{
    my($self) = $_[0];
    my($flagBoolean) = $self->;{"flag"};
    if ($flagBoolean eq "1")
    {
       update();
    }else{
        insert();
    }
}

sub update{
}

sub insert{
}

希望update和insert都是abstract method,调用时自动根据继承的Female.pm中的实际update和insert方法来实现功能.
小弟是java delveloper,不了解如何在Perl中实现abstract method.希望大侠给一段code让我参考.



 笨狗 回复于:2005-08-11 07:26:09

abstract不是抽象吗?怎么变成虚了?


 笨狗 回复于:2005-08-11 07:27:07


package Vater;

sub new {
  my($proto)=@_;
  my $class = ref($proto) || $proto;
  my $self = {};
  bless($self, $class);
  return $self;
}

sub check {
  die "Abstract method not defind";
}
1;




package Sohn;

use Vater;
use vars qw(@ISA);
@ISA = ("Vater");

sub {
  my ($proto) = @_;
  my $class = ref($proto) || $proto;
  my $self = $class->;SUPER::new();
  
  bless($self, $class);
  return $self;
}

sub check {
  my ($self) = @_;
  # do something
}
1;




use Sohn;

my $s = Sohn->;new();
$s->;check();



 guweichen 回复于:2005-08-12 04:21:43

谢谢 苯狗,
可能我问题描述不清楚.
我希望
update和insert都是abstract并且在子类中被override.
子类中不orveride save(), save的用法在父类中已经定义.(所以save不时abstract)
当使用子类的save()时,实际调用的是在子类中的update和insert
这通常在java中很容易实现,java中的OO比较强,但是现在项目是Perl,我没经验,发现Perl的OO很不方便.有没有好的实现方法?我用了Class::Virtually::Abstract,
Attribute::Abstract,都不行,是不是不能实现,还是我用得不对?新手啊!!!请帮忙


 guweichen 回复于:2005-08-12 04:49:01

还有,Vater 在new的时候加$self->;{'name'} = "1";在Sohn->;new();后访问不到'name',所谓的abstract object,它的constructor不一定是abstract,子类应该可以访问父类的被继承的成员变量的. 到了Perl的object中就不一样了. 是不是perl object真是这样啊?


 guweichen 回复于:2005-08-12 04:53:36

不好意思,赫赫 
说到底,就是想用perl中的OO实现多态(polymorphism)


 笨狗 回复于:2005-08-12 06:01:47

建议楼主先看一些文档
比如http://pleac.sourceforge.net/pleac_perl/classesetc.html


 笨狗 回复于:2005-08-12 06:02:51

引用:原帖由 "guweichen" 发表:
不好意思,赫赫 
说到底,就是想用perl中的OO实现多态(polymorphism)


不好意思,我不懂什么是多态


 笨狗 回复于:2005-08-12 06:04:48

引用:原帖由 "guweichen"]还有,Vater 在new的时候加$self->;{'name'} = "1";在Sohn->;new();后访问不到'name',所谓的abstract object,它的constructor不一定是abstract,子类应该可以访问父类的被继承的成员变量的. 到了Perl的object中就?.........
 发表:


$self是一个hash的引用,应该这样定义

$self->;{NAME =>; 1};



 笨狗 回复于:2005-08-12 06:08:44

引用:原帖由 "guweichen" 发表:
谢谢 苯狗,
可能我问题描述不清楚.
我希望
update和insert都是abstract并且在子类中被override.
子类中不orveride save(), save的用法在父类中已经定义.(所以save不时abstract)
当使用子类的save()时,实际调用?.........


难道我写的check()不是一个抽象方法?
perl的OO也不是很麻烦,除了bless()有点奇怪,其他和java大同小异,OO的思想都是一样的
你可以在父类和子类中都定义update和insert方法, 在父类中定义save方法,在子类中不要定义save方法


 guweichen 回复于:2005-08-12 21:40:49

引用:原帖由 "笨狗" 发表:

难道我写的check()不是一个抽象方法?
perl的OO也不是很麻烦,除了bless()有点奇怪,其他和java大同小异,OO的思想都是一样的
你可以在父类和子类中都定义update和insert方法, 在父类中定义save方法,在子类中不要定义..........



我正是这样做的,但是在执行子类save的方法的时候,单步调试显示,实际调用的是父类中的update和insert方法,并不是子类中overriden的update和insert.


 笨狗 回复于:2005-08-13 01:22:40

引用:原帖由 "guweichen" 发表:


我正是这样做的,但是在执行子类save的方法的时候,单步调试显示,实际调用的是父类中的update和insert方法,并不是子类中overriden的update和insert.


贴code吧


 flw 回复于:2005-08-13 14:51:53

Perl 的 OO 本来就支持多态和继承的,不需要任何额外的技巧,只需要注意 @ISA 这个数组就可以了。
D:\MoChou>;cat ttt.pl

#!/usr/bin/perl
use strict;
use warnings;

package ParentClass;
our @ISA = qw(Exporter);

sub new{
    my $class = shift;
    return bless {}, $class;
}

sub hello{
    print "Hello!\n";
}

sub greet{
    &hello();
}

package ChildClass;
our @ISA = qw(Exporter ParentClass);

sub new{
    my $class = shift;
    return bless {}, $class;
}

sub roar{
    print "Kao!\n";
}

sub greet{
    &roar();
}

package main;
my $gent = new ParentClass;
my $cur = new ChildClass;

$gent->;greet();
$cur->;greet();

$cur->;hello();
$gent->;coar();

D:\MoChou>;ttt
Hello!
Kao!
Hello!
Can't locate object method "coar" via package "ParentClass" at D:\MoChou\ttt.pl
line 45.

D:\MoChou>;

一个斯文的父亲生下了一个粗鲁的儿子,
斯文的父亲在问候别人的时候会说 “hello”,而粗鲁的儿子只会 “Kao”
同样的问候,在父子之间呈现出了多态性。
但是,儿子并不是不会说 hello,他也会说,这里呈现出了继承的概念。
只是这个粗鲁的家伙在问候的时候没有说 hello 的习惯而已,取而代之的是变异出来的嚎叫。可怜的父亲对此一无所知,所以你就算是让父亲嚎叫他也叫不出来。


 flw 回复于:2005-08-13 15:29:08

刚才又仔细审了一下题目,
发现我上面给出的并不能解决楼主的问题。
下面再写一个:
D:\MoChou>;cat ttt.pl

#!/usr/bin/perl
use strict;
use warnings;

package ParentClass;
our @ISA = qw(Exporter);

sub new{
    my $class = shift;
    return bless {}, $class;
}

sub howto_greet{
    return "Hello!";
}

sub greet{
    my $class = shift;
    my $msg = $class->;howto_greet();
    print "$msg\n";
}

package ChildClass;
our @ISA = qw(Exporter ParentClass);

sub new{
    my $class = shift;
    return bless {}, $class;
}

sub howto_greet{
    return "Kao!";
}

package main;
my $gent = new ParentClass;
my $cur = new ChildClass;

$gent->;greet();
$cur->;greet();

D:\MoChou>;ttt
Hello!
Kao!

D:\MoChou>;

子类并没有定义 greet,只是简单地继承了父类的 greet,
greet 函数首先思考如何去问候对方,这个通过 howto_greet 来实现,
考虑好问候语之后,print 出来。
很显然,在上面的例子中,子类重写了父类的 howto_greet,因此虽然调用的是父类的 greet,但是父类的 greet 调用的却是子类的 howto_greet。


 flw 回复于:2005-08-13 15:30:14

如果子类不定义 howto_greet 又将如何呢?
答案是子类会继承父类的 howto_greet,因此上面的代码并不会出错。
具体代码我就不给出了,作为练习由楼主自己来完成。


 flw 回复于:2005-08-13 15:31:11

引用:原帖由 "guweichen"]我正是这样做的,但是在执行子类save的方法的时候,单步调试显示,实际调用的是父类中的update和insert方法,并不是子类中overriden的update和insert.
 发表:


记得调用的时候加上 $class->; 前缀。

update() =>; $class->;update()


 笨狗 回复于:2005-08-13 17:27:00

呓,大版主来了,小声的问一下,多态是虾米意思?


 flw 回复于:2005-08-13 18:51:02

引用:原帖由 "笨狗"]呓,大版主来了,小声的问一下,多态是虾米意思?
 发表:


你考我呢吧?
我也不太懂~ 我只会用。 :oops:  :oops:  :oops:  :oops:


 笨狗 回复于:2005-08-14 01:06:58

引用:原帖由 "flw" 发表:

你考我呢吧?
我也不太懂~ 我只会用。 :oops:  :oops:  :oops:  :oops:


我确实是不知道多态是什么意思


 流言飞语 回复于:2005-08-16 17:03:56

我想,你所谓的多态是不是在函数上这样表现:

func(baseclass a)
{
  a.test();
}

baseclass中有一个虚函数test
inheritclass派生类中也有一个虚函数函数test
那么你想在调用func时内部执行的a.test是inheritclass中的test
是不是这样?


 流言飞语 回复于:2005-08-16 17:12:14

可能是这个问题:

sub save{ 
   my($self) = $_[0]; 
   my($flagBoolean) = $self->;{"flag"}; 
   if ($flagBoolean eq "1") 
   { 
      $self->;update(); 
   }else{ 
       $self->;insert(); 
   } 


sub update{ 


sub insert{ 




 流言飞语 回复于:2005-08-16 17:34:31

我已经测试过了,楼主所说的虚函数问题在perl中本来就是默认解决的,你在调用update和insert时要使用$self->;调用,这样系统才会以当前对象作为调用对象,调用派生类的update和insert函数,实现你需要的多态。
我测试的代码:

package A;

sub new
{
my $class=shift;
my $self={};
$self->;{name}="A";
bless $self,$class;
return $self;
}
sub who
{
my $self=shift;
$self->;intr;
}
sub intr
{
print "i an A\n";
}
1;
----
package AA;
use A;
use vars qw(@ISA);

@ISA=qw (A);

sub new
{
my $class=shift;
my $self=$class->;SUPER::new(@_);
bless $self,$class;
return $self;
}

sub intr
{
print "I an AA\n";
}
1;
---
#主程序
use strict; 
use warnings;
use A;
use AA;
my $a=new A;
my $aa=new AA;

$aa->;who;
$a->;who;



 流言飞语 回复于:2005-08-19 10:25:57

期待该帖主的结果




原文链接:http://bbs.chinaunix.net/viewthread.php?tid=591739
转载请注明作者名及原文出处