为什么perl对象实例彼此覆盖 [英] Why does perl object instance overwrite each other
问题描述
我写了一些 Perl
代码,它们构成了基本类固有的两个类。我想它会打印这样
I've written some Perl
code which compose 2 classes inherent from a base one. I suppose it would print something like this
Mik: Meow! Meow!
Sat: Woof! Woof!
但实际上是这样打印的:
But it actually print this way:
Sat: Woof! Woof!
Sat: Woof! Woof!
,
package Animal;
sub new {
my $obj = shift;
my $name = shift;
our %pkg = ( 'name' => $name );
bless \%pkg, $obj;
return \%pkg;
}
package Cat;
@ISA = ("Animal");
sub new {
my $obj = shift;
my $name = shift;
my $self = $obj->SUPER::new($name);
return $self;
}
sub get_name {
my $obj = shift;
return $obj->{'name'};
}
sub talk {
my $obj = shift;
return "Meow! Meow!";
}
package Dog;
@ISA = ("Animal");
sub new {
my $obj = shift;
my $name = shift;
my $self = $obj->SUPER::new( $name );
return $self;
}
sub get_name {
my $obj = shift;
return $obj->{'name'};
}
sub talk {
my $obj = shift;
return "Woof! Woof!";
}
package Main;
my $cat = new Cat('Mike');
my $dog = new Dog('Sat');
print $cat->get_name() . ": " . $cat->talk() , "\n";
print $dog->get_name() . ": " . $dog->talk() , "\n";
但是如果我以这种方式更改调用者,它会打印我想要的。所以很奇怪为什么 $ cat
对象在 $ dog
实例化后被覆盖了?
But if I change the caller in this way, it prints what I suppose to be. So it is quite strange why the $cat
object was overwritten after the $dog
was instantiated ?
package Main;
my $cat = new Cat('Mily');
print $cat->get_name() . ": " . $cat->talk() , "\n";
my $dog = new Dog('Sat');
print $dog->get_name() . ": " . $dog->talk() , "\n";
推荐答案
将您的构造函数更改为:
Why do you bless into a global variable? Change your constructor to:
sub new {
my $obj = shift;
my $name = shift;
my %pkg = ( 'name' => $name );
bless \%pkg, $obj;
return \%pkg;
}
更好的是,将其改为更惯用的:
Better yet, change it to something more idiomatic:
sub new {
my $class = shift;
my $name = shift;
my $self = { name => $name };
return bless $self, $class;
}
继续:
为什么在每种动物上实现 new
和 get_name
?这两种方法都可以继承。虽然我们在这里,我们也可以摆脱对 @ISA
:
Why implement new
and get_name
in each kind of animal? Both methods can be inherited. While we're at it, we might as well get rid off the messing around with @ISA
:
package Animal;
sub new {
my $class = shift;
my $name = shift;
my $self = { name => $name };
return bless $self, $class;
}
sub get_name {
my $self = shift;
return $self->{'name'};
}
package Cat;
use base qw/ Animal /;
sub talk {
my $self = shift;
return "Meow! Meow!";
}
package Dog;
use base qw/ Animal /;
sub talk {
my $self = shift;
return "Woof! Woof!";
}
package Main;
my $cat = Cat->new('Mike');
my $dog = Dog->new('Sat');
print $cat->get_name() . ": " . $cat->talk() , "\n";
print $dog->get_name() . ": " . $dog->talk() , "\n";
我可以问您正在跟着哪一本教程或书?
May I ask which tutorial or book you are following?
虽然上面的是完全正常的,你也可以做现代Perl的方式:
While the above is perfectly fine, you might as well do it the Modern Perl way:
package Animal;
use Moose;
has name => ( required => 1, is => 'rw', isa => 'Str' );
package Cat;
use Moose;
extends 'Animal';
has talk => ( default => "Meow! Meow!", is => 'ro' );
package Dog;
use Moose;
extends 'Animal';
has talk => ( default => "Woof! Woof!", is => 'ro' );
package Main;
my $cat = Cat->new( name => 'Mike');
my $dog = Dog->new( name => 'Sat');
print $cat->name . ": " . $cat->talk , "\n";
print $dog->name . ": " . $dog->talk , "\n";
这篇关于为什么perl对象实例彼此覆盖的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!