Perl:Come posso chiamare i metodi dell'oggetto all'interno di END {} senza preavviso?

StackOverflow https://stackoverflow.com/questions/1914730

  •  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.

È stato utile?

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 .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top