6 Stimmen

Aufruf von SUPER::new()

Ich habe zwei Möglichkeiten gesehen, die new Methode in einer abgeleiteten Klasse.

Methode eins:

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

Methode zwei:

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);
}

Ich bin mir nicht sicher, ob ich verstehe, worin der Unterschied besteht. Kann mir das bitte jemand erklären?


Aus Ihren Kommentaren und Antworten kann ich entnehmen, dass die ref() Teil ist schlecht.

Aber was ist mit der Verwendung von SUPER::new(@_) ? Im ersten Beispiel wird der Hashref in der abgeleiteten Klasse gesegnet und dann wird das Objekt SUPER 's new aufgerufen und in demselben Objekt gespeichert wird.

Im zweiten Beispiel hingegen wird ein Basisobjekt aus der Klasse SUPER s new Methode, und diese wird in die neue Klasse aufgenommen.

Worin besteht der Unterschied zwischen diesen beiden Möglichkeiten? Es sieht so aus, als ob die erste Methode das Objekt mit dem Basisobjekt überschreibt. Die zweite scheint "doppelt zu segnen". Ich bin verwirrt.

9voto

Dallaylaen Punkte 5208

Warum nicht einfach:

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

-- mit der einzigen Ausnahme für die tiefste Basisklasse in der Hierarchie, die entweder bless $self, $class; oder vielleicht my $self = fields::new($class); für den Fall, dass Sie use fields .

6voto

pilcrow Punkte 53851

Update

Sie fragen:

Worin besteht der Unterschied zwischen diesen beiden Möglichkeiten? Es sieht so aus, als ob die erste Methode das Objekt mit dem Basisobjekt überschreibt. Die zweite scheint "doppelt zu segnen". Ich bin verwirrt.

Nur Mut. Jede der beiden von Ihnen vorgestellten Methoden ist in sich verworren, und keine von beiden sollte nachgeahmt werden.

Methode eins segnet ein Objekt der Klasse DerivedClass ab und verwendet dann dieses Objekt, um den Allokator/Konstruktor einer AncestorClass aufzurufen, die sich selbst ersetzt. Nun, AncestorClass::new verwendet wahrscheinlich auch die unglückliche ref($yuck) || $yuck Idiom, was bedeutet, dass das neue Objekt in DerivedClass gesegnet wird. Ein DerivedClass-Objekt wird also verwendet, um ein anderes zu konstruieren, das es ersetzt. Fragwürdig.

Methode zwei gibt ihren Empfänger ($self) zurück, wenn der Empfänger ein Objekt ist. (Beachten Sie, dass ref($self) wird zweimal geprüft, obwohl es nur einmal geprüft werden muss). Das heißt, $o->new() gibt genau dasselbe zurück $o nach Methode zwei. Wenn der Empfänger n ein Objekt, sondern einen Klassennamen, das heißt, wenn wir stattdessen DerivedClass->new , dann wird AncestorClass::new aufgerufen. Aber das erste Argument der Methode der Superklasse ist "DerivedClass", und vermutlich kodiert die Superklasse ihre bless Die anschließende erneute Segnung ist also sinnlos.

Machen Sie sich einfach keine Sorgen über diese Beispiele. Bitte konsultieren Sie stattdessen perlobj et perlootut für eine sichere und vernünftige Verwendung von SUPER.

Ursprüngliche Antwort

Ach, meine Augen!

Methode eins ist, wie daxim bemerkte, ein unzulässiges Mittel, um ein Objekt aus derselben Klasse wie ein bestehendes Objekt zu konstruieren:

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.

Methode zwei ist (glaube ich) eine Abhilfe für diese verwirrende Praxis. Ihre Methode zwei gibt die dasselbe Objekt もし new() genannt wird.

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.

Benutzen Sie beides nicht :) Es mag einige Anwendungen geben, bei denen eine der beiden oben genannten Semantiken vollkommen sinnvoll ist. Ich würde diese Methode nur nicht so nennen new() in diesen Anwendungen...

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X