2012-11-16 15 views
8

Ho un oggetto base chiamato RuleObject e un oggetto che eredita da quello chiamato RuleObjectString. Ho un nuovo metodo in RuleObjectString che voglio chiamare nel mio codice che usa quell'oggetto. Ma ottengo l'errore. 'Impossibile trovare il metodo dell'oggetto "compare" tramite il pacchetto "RuleObject" in ./testobject.pl riga 10. " Ma non sto creando un RuleObject. Sto creando un RuleObjectString. Cosa sto facendo di sbagliato qui?Estensione di un oggetto in Perl

testobject.pl

1 #! /usr/bin/perl 
    2 
    3 use strict; 
    4 
    5 use RuleObjectString; 
    6 
    7 my $s = RuleObjectString->new(); 
    8 $s->value('stuff goes here'); 
    9 
10 if ($s->compare('stuff')){ 
11   print "MATCH!\n"; 
12 }else{ 
13   print "no match :(\n"; 
14 } 

RuleObject.pm

package RuleObject; 

our @ISA = qw/Exporter/; 
our @EXPORT = qw/new/; 

use strict; 

sub new{ 
     my $class = shift; 

     my $self; 
     $self->{value} = undef; 

     bless $self; 
     return $self; 
} 

sub value{ 
     my $self = shift; 
     my $value = shift; 
     if ($value){ 
       $self->{value} = $value; 
     }else{ 
       return $self->{value}; 
     } 
} 

RuleObjectString.pm

package RuleObjectString; 

our @ISA = qw/RuleObject/; 
our @EXPORT = qw/compare/; 

use strict; 

sub compare{ 
     my $self = shift; 
     my $compareto = shift; 

     return $self->value() =~ /$compareto/; 
} 
+6

Non si dovrebbe '@ EXPORT' i metodi della classe e dell'istanza ei moduli in genere non dovrebbero ereditare' Exporter' a meno che non abbiano funzioni procedurali in buona fede da esportare. – pilcrow

+0

E per i casi in cui è necessario esportare * funzioni *, 'Sub :: Exporter' è molto più interessante rispetto a' Exporter'. Ma probabilmente dovresti evitare di esportare le funzioni dai pacchetti che sono anche definizioni di classi. ' –

risposta

12

Penso che jmcneirney sia sulla strada giusta. Nella tua RuleObject costruttore, si dice

bless $self; 

, che è lo stesso di

bless $self, __PACKAGE__; 

o

bless $self, 'RuleObject' 

ma quello che vogliamo è che l'oggetto benedetto come RuleObjectString. Quindi, ciò che si vuole fare è dire

bless $self, $class 

Ora

RuleObject->new() 
RuleObjectString->new() 

saranno entrambi chiamare lo stesso costruttore, ma l'oggetto restituito dalla prima chiamata sarà benedetto come un RuleObject e il secondo oggetto sarà benedetto come RuleObjectString.

+0

Questo ha fatto il trucco! Grazie! – Mike

0

Prova di dumping l'oggetto e vedere di cosa si tratta.

print Dumper($s) 

Sarà un RuleObject.

Potrebbe essere necessario definire un nuovo() in RuleObjectString e chiamarlo Super :: new().

+0

Non necessario; il bug è come commentato in precedenza. Vale a dire, l'uso di 'bless()' non qualificato per benedire il pacchetto chiamante, non il nome della classe fornito. – LeoNerd

5

Questo è il 2012, quindi è consigliabile prendere in considerazione l'utilizzo di soluzioni OOP appropriate invece di reinventare nuovamente la ruota.

Utilizzando Moose, la soluzione sarebbe simile a questa (non testata):

RuleObject.pm

package RuleObject; 
use Moose; 

has 'value' => (isa => 'Str', is => 'rw', required => 0, default => ''); 

1; 

RuleObjectString.pm

package RuleObjectString; 
use Moose; 

extends 'RuleObject'; 

sub compare { 
    my $self  = shift; 
    my $compareto = shift; 

    return $self->value =~ /$compareto/; 
} 

1; 

semplice! :)

+2

E per le persone che pensano che "Moose" sia troppo pesante, "Moo" è un'alternativa molto valida e leggera. –

+1

Non è bello capire come funziona la lingua e non fare affidamento solo sulle soluzioni di libreria? (Essendo il 2014 e il mondo quasi invaso dagli sviluppatori.) – jackyalcine

+0

OP voleva risolvere un problema specifico, non imparare Perl. Le biblioteche ci sono per una buona ragione. :) – toreau

Problemi correlati