我正在做一个Perl OO示例(主要是为了重新使用Perl重新定义)并使用 继承,似乎SUPER在调用超类构造函数时在子类中工作 超类变量不绑定到子类对象。为什么会这样?
################################################
## Package : Person ##
################################################
package Person;
################################################
## Constructor ##
################################################
sub new(){
my $class = shift;
my $data = {};
$data->{'firstName'} = shift;
$data->{'secondName'} = shift;
bless $data, $class;
#bless $data, "Person"; #hack
return $data;
}
################################################
## Getter Methods ##
################################################
sub getFirstName(){
my $data = shift;
return $data->{'firstName'};
}
sub getSecondName(){
my $data = shift;
return $data->{'secondName'};
}
################################################
## Setter methods ##
################################################
sub setFirstName($){
my $data = shift;
$data->{'firstName'} = shift;
}
sub setSecondName($){
my $data = shift;
$data->{'secondName'} = shift;
}
################################################
## Other Methods ##
################################################
sub printall(){
my $data = shift;
$\ = "\n";
print "FirstName: ". $data->{'firstName'} ."\n";
print "SecondName: ". $data->{'secondName'} ."\n";
}
1;
################################################
## Package : Coder ##
################################################
package Coder;
@ISA = qw( Person );
use strict;
use warnings;
################################################
## Constructor ##
################################################
sub new {
my $class = shift;
my $self = {};
bless $self, $class;
my $superFirstName = shift;
my $superSecondName = shift;
print "new superfirstname " .$superFirstName;
print "new supersecondname " .$superSecondName;
$self->{'language'} = shift; #i.e. Java
$self->{'experience'} = shift; #number of years
#$self = $self->SUPER::new($superFirstName, $superSecondName);
Person->new($superFirstName, $superSecondName);
return $self;
}
################################################
## Getter Methods ##
################################################
sub getLanguage(){
my $data = shift;
return $data->{'language'};
}
sub getExperience(){
my $data = shift;
return $data->{'experience'};
}
################################################
## Setter methods ##
################################################
sub setLanguage($){
my $data = shift;
$data->{'language'} = shift;
}
sub setExperience($){
my $data = shift;
$data->{'experience'} = shift;
}
################################################
## Other Methods ##
################################################
sub printall(){
my $data = shift;
$\ = "\n";
print "Experience: " . $data->{'experience'};
print "Language: " . $data->{'language'};
$data->SUPER::printall();
}
1;
################################################
## Package : Main ##
################################################
package main;
my $developer = Coder->new("John","Smith","Perl","2");
$developer->printall();
答案 0 :(得分:3)
如果您打算将Coder继承自Person,那么您正在构建它 不正确。例如,在Coder的构造函数中,您将创建一个新的Person对象 扔掉它。这将是一种更好(更标准)的方式 构造一个继承自Person的Coder对象(参见perldoc perltoot):
sub new
{
my $class = shift;
my $this = $class->SUPER::new(shift, shift);
# add on extra fields, now at the head of @_...
bless $this, $class;
return $this;
}
您可以进行许多改进:
use strict; use warnings;
use parent 'Person';
而不是操纵@ISA 另外,虽然我不确定你是否准备好了(你应该明白这一点 首先是Perl OO构建的基础知识,你可以跳过几乎所有的写作 此代码使用Moose:
package Person;
use Moose;
has [qw(firstName secondName)] => (
is => 'rw', isa => 'Str',
);
no Moose;
__PACKAGE__->meta->make_immutable;
1;
package Coder;
use Moose;
extends 'Person';
has [qw(language experience)] => (
is => 'rw', isa => 'Str',
);
no Moose;
__PACKAGE__->meta->make_immutable;
1;
答案 1 :(得分:3)
这是因为您没有对Person->new
返回做任何事情。所以它只是创建一个整个其他Person
对象,而Coder
快乐地滑行。
你想做的是
my $self = $class->SUPER::new( $superFirstName, $superSecondName );
让Person
保佑它进入你传递的任何课堂 - 就像它一样。然后,在创建$self
SUPER
方式后,您需要为其添加所需的字段。
所以看起来应该是这样的:
use strict;
use warnings;
sub new {
my $class = shift;
my $superFirstName = shift;
my $superSecondName = shift;
print "new superfirstname " .$superFirstName;
print "new supersecondname " .$superSecondName;
my $self = $class->SUPER::new( $superFirstName, $superSecondName );
# OR
# $self = $class->Person::new( $superFirstName, $superSecondName );
$self->{language} = shift; #i.e. Java
$self->{experience} = shift; #number of years
return $self;
}
答案 2 :(得分:2)
Coder
的构造函数没有意义;您正在调用Person->new
,然后丢弃结果。这是一个更有用的模式:
package Coder;
sub new {
my $class = shift;
my $self = $class->SUPER::new(shift, shift); # firstname, lastname
$self->{language} = shift;
$self->{experience} = shift;
$self;
}
是的,Person
构造函数会在这种情况下将对象加入Coder
,而不是加入Person
- 这就是将类作为{{1的第一个参数}}
这是您的代码的最小更改版本,但我想在此之外提出一些建议:
构造函数的位置参数是确保没有人知道发生了什么的好方法。我建议输入new
等。
您可能最好忘记所有这些苦差事并使用Moose:)