6

new派生クラスにメソッドを実装する2つの方法を見てきました。

方法1:

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

方法2:

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

違いが何なのかわかりません。誰か説明してもらえますか?


ref()あなたのコメントと回答から、その部分が悪いことがわかります。

しかし、の使用はSUPER::new(@_)どうですか?最初の例では、hashrefが派生クラスに祝福されてから、そのオブジェクトのSUPERnew呼び出され、同じオブジェクトに保存されます。

一方、2番目の例では、ベースオブジェクトがクラスのメソッドから作成され、SUPERそれnewが新しいクラスに祝福されます。

これら2つの方法の違いは何ですか?最初のオブジェクトがベースオブジェクトで上書きされているようです。2番目は「二重の祝福」のようです。よくわかりません。

4

2 に答える 2

9

なぜだけではないのですか?

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

--階層内で最も深い基本クラスを除いて、いずれかを呼び出すかbless $self, $class;my $self = fields::new($class);場合によっては呼び出す必要がありますuse fields

于 2012-06-08T19:57:36.853 に答える
6

アップデート

あなたが尋ねる:

これら2つの方法の違いは何ですか?最初のオブジェクトがベースオブジェクトで上書きされているようです。2番目は「二重の祝福」のようです。よくわかりません。

心を取ります。表示する2つの方法はそれぞれそれ自体が混乱しているため、どちらもエミュレートする必要はありません。

メソッド1は、クラスDerivedClassのオブジェクトを祝福して存在させ、そのオブジェクトを使用して、AncestorClassのアロケーター/コンストラクターを呼び出し、それ自体を置き換えます。現在、AncestorClass :: newもおそらく不幸なref($yuck) || $yuckイディオムを使用しています。これは、新しいオブジェクトがDerivedClassに祝福されることを意味します。したがって、1つのDerivedClassオブジェクトを使用して、別のオブジェクトを作成し、それを置き換えます。疑わしい。

方法2は、レシーバーがオブジェクトの場合、レシーバー($ self)を返します。(1回だけチェックする必要がある場合は2回チェックされることに注意してくださいref($self)。)つまり、メソッド2で$o->new()まったく同じものを返します。$oレシーバーがオブジェクトではなくDerivedClass->newクラス名である場合、つまり、代わりにを呼び出した場合は、AncestorClass::newが呼び出されます。しかし、スーパークラスのメソッドの最初の引数は「DerivedClass」であり、おそらくスーパークラスはそのblessedパッケージ名をハードコーディングしていないため、その後の再祝福は無意味です。

これらの例については心配しないでください。代わりに、SUPERの安全で正しい使用法については、 perlobjperlootutに相談してください。

元の回答

ああ、私の目!

方法1は、daximがコメントしたように、既存のオブジェクトと同じクラスからオブジェクトを構築できるようにするための好ましくない手段です。

my $o1 = MethodOne->new();
my $o2 = $o1->new();        # $o2 is a clone of $o1.  No, wait, it isn't!
                            # It's a brand new, "empty" object.  Ha,
                            # fooled you.

方法2は、(私が思うに)この紛らわしい慣行の回避策です。 メソッド2は、が呼び出された場合、まったく同じオブジェクトを返します。new()

my $o1 = MethodTwo->new();
my $o2 = $o1->new();         # $o2 is a new MethodTwo.  No, wait, it isn't!
                             # It's a brand new object.  No, wait, it isn't!
                             # It's a /exactly the same object/ as $o1.  Ha,
                             # fooled you.

どちらも使用しないでください。:)上記のセマンティクスのいずれかが完全に理にかなっているアプリケーションがいくつかあるかもしれません。私はそれらのアプリケーションでそのメソッドnew()に名前を付けません...

于 2012-06-08T15:20:50.863 に答える