为什么perl对象实例彼此覆盖 [英] Why does perl object instance overwrite each other

查看:150
本文介绍了为什么perl对象实例彼此覆盖的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了一些 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆