Perl:Come posso chiamare i metodi dell'oggetto all'interno di END {} senza preavviso?
-
19-09-2019 - |
Domanda
package JustTesting;
use strict;
use warnings;
sub new {
my $self = {};
bless($self, shift);
END { $self->goodbye() };
return $self;
}
sub goodbye {
print "Goodbye.\n";
}
package main;
my $this = JustTesting->new();
Produzione:
La variabile "$self" non rimarrà condivisa alla riga ./test 10.
Arrivederci.
Apparentemente funziona e posso eliminare l'avviso con no
warnings
all'interno del blocco END.Ma mi chiedo se c'è un modo migliore come farlo.
Ho provato a utilizzare un sub anonimo come questo:
my $cleanup = sub { $self->goodbye() };
END { $cleanup->() };
e poi in questo modo:
END { sub { $self->goodbye() }->() };
Ma ricevo sempre lo stesso avvertimento.
Soluzione
È molto probabilmente si desidera DESTROY
invece di END
. Vedi la sezione sulla distruttori in perltoot .
package JustTesting;
use strict;
use warnings;
sub new {
my $self = {};
bless($self, shift);
return $self;
}
sub goodbye {
print "Goodbye.\n";
}
sub DESTROY {
my ($self) = @_;
$self->goodbye()
};
package main;
{
say "entering scope";
my $this = JustTesting->new();
say "leaving scope";
}
say "left scope";
Output:
entering scope leaving scope Goodbye. left scope
Altri suggerimenti
Solo per riferimento ai futuri lettori Ho allegato una versione Moose
di daxim s 'corretto risposta .
use 5.012;
use warnings;
{
package JustTesting;
use Moose;
use namespace::clean -except => 'meta';
sub goodbye { say "Goodbye." }
sub DEMOLISH {
my ($self) = @_;
$self->goodbye;
}
}
{
say "entering scope";
my $this = JustTesting->new();
say "leaving scope";
}
say "left scope";
Si noti l'uso della subroutine DEMOLISH
per il distruttore .
NB. Troverete che distruggono funziona ancora, ma è il modo DEMOLIRE Moosey corretto di farlo.
/ I3az /
In primo luogo, vedere my()
Scoped variabile in sottoprogrammi annidati per una spiegazione.
In secondo luogo, penso che si dovrebbe usare sia DESTROY
o una classe di supporto a seconda ciò che si sta cercando di ottenere.
Il motivo dell'avvertimento è perché, anche se non sembra, perl an END
block è equivalente alla dichiarazione di un sottotitolo regolare (con nome) e il comportamento di un sottotitolo con nome dichiarato all'interno di un altro sottotitolo non è quello che desideri -- $self
dentro il END
il blocco sarà associato $self
In sub new
IL Primo tempo quello new
viene chiamato e continuerà a vedere lo stesso valore - la primissima istanza creata - per il resto della vita del tuo programma.La prima istanza avrà un riferimento detenuto dal END
blocchi e non verrà distrutto fino alla fine del programma, e tutte le istanze successive non lo avranno END
block li ha chiamati affatto.
A differenza dei sottotitoli con nome, i sottotitoli anonimi non hanno questo problema perché vengono ricostruiti ogni volta che viene incontrata la loro definizione, quindi tutte le variabili su cui si chiudono vengono associate il più tardi possibile e i valori effettivamente desiderati vengono catturati.
Questa è una spiegazione piuttosto lunga quando altri ti hanno già detto che quello che vuoi è DESTROY
invece, ma ho pensato che ti avrebbe fatto piacere sapere di cosa si tratta In realtà succedendo con il codice che hai scritto.
Con il tempo il blocco END
è chiamato, $ pulizia è già stato deallocato. Per fare qualsiasi lavoro con una variabile, è necessario utilizzare un distruttore, invece.
Vedere "distruttori" a perldoc perltoot .