2012-11-16 19 views
8

Ich habe ein Basisobjekt namens RuleObject und ein Objekt, das von dem namens RuleObjectString erbt. Ich habe eine neue Methode in RuleObjectString, die ich in meinem Code aufrufen möchte, der dieses Objekt verwendet. Aber ich bekomme den Fehler. 'Die Objektmethode "compare" kann nicht über das Paket "RuleObject" in der Zeile ./testobject.pl gefunden werden.' Aber ich erstelle kein RuleObject. Ich erstelle einen RuleObjectString. Was mache ich hier falsch?Erweitern eines Objekts 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

Sie sollten Ihre Klassen- und Instanzmethoden nicht "EXPORTIEREN", und Ihre Module sollten normalerweise nicht "Exporter" erben, es sei denn, sie haben bona fide prozedurale Funktionen zum Exportieren. – pilcrow

+0

Und für Fälle, in denen Sie * Funktionen * exportieren müssen, ist 'Sub :: Exporter' viel nutzerfreundlicher als' Exporter'. Sie sollten jedoch wahrscheinlich vermeiden, Funktionen aus Paketen zu exportieren, die ebenfalls Klassendefinitionen sind. ' –

Antwort

12

Ich denke, jmcneirney ist auf dem richtigen Weg. In Ihrem RuleObject Konstruktor, sagen Sie

bless $self; 

die als

die gleiche ist
bless $self, __PACKAGE__; 

oder

bless $self, 'RuleObject' 

aber was Sie wollen, ist für das Objekt gesegnet als RuleObjectString. Also, was Sie tun möchten, ist zu sagen

bless $self, $class 

Jetzt

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

den gleichen Konstruktor beide nennen, aber das Objekt durch den ersten Aufruf zurückgegeben wird als RuleObject und das zweite Objekt gesegnet sein wird gesegnet als RuleObjectString.

+0

Das hat den Trick gemacht! Vielen Dank! – Mike

0

das Objekt Dumping versuchen und sehen, was es ist.

print Dumper($s) 

Es wird ein RuleObject sein.

Sie müssen möglicherweise eine neue() in RuleObjectString definieren und Super :: new() aufrufen.

+0

Nicht notwendig; Der Fehler ist wie zuvor erwähnt. Nämlich die Verwendung von unqualifizierten 'bless()', um in das aufrufende Paket zu segnen, nicht den angegebenen Klassennamen. – LeoNerd

5

Das ist 2012, also sollten Sie überlegen, richtige OOP-Lösungen zu verwenden, anstatt das Rad neu zu erfinden.

von Moose verwenden, wäre die Lösung so etwas wie dieses (nicht getestet) aussehen:

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; 

einfach! :)

+2

Und für Leute, die denken, 'Moose' ist zu schwer,' Moo' ist eine sehr gute leichte Alternative. –

+1

Ist es nicht gut zu verstehen, wie die Sprache funktioniert und sich nicht nur auf Bibliothekslösungen zu verlassen? (Es wird 2014 und die Welt fast mit Entwicklern überlaufen.) – jackyalcine

+0

OP wollte ein bestimmtes Problem lösen, Perl nicht lernen. Die Bibliotheken gibt es aus gutem Grund. :) – toreau