2010-08-30 4 views
6

Überall, besonders in DBI, sehe ich diese Nachricht die ganze Zeit auftauchen. Es ist verwirrend, denn das erste, was mir in den Sinn kommt, ist, dass die Argumente, die ich an die Funktion übergebe, auf undef (oder etwas Ähnliches) gesetzt werden, aber das ist eindeutig nicht der Fall.

ein Modul und ein entsprechendes Skript gegeben ...

Modul: ./lib/My/Module.pm

package My::Module; 

use strict; 
use warnings; 

sub trim { 
    my $str = shift; 
    $str =~ s{ \A \s+ }{}xms; # remove space from front of string 
    $str =~ s{ \s+ \z }{}xms; # remove space from end of string 
    return $str; 
} 

Script: ./test.pl

#!/usr/bin/perl 

use strict; 
use warnings; 
use My::Module qw(trim); 

print $My::Module->trim(" \t hello world\t \t"); 

I Nachricht

zurück den Fehler

Ca nicht nennen Methode „trimmen“ auf einen nicht definierten Wert an ./text.pl Linie 7.

Infact, wenn ich rufe $My::Module->notamethod("hello world"); es einen ähnlichen Fehler gibt.

Was ist los mit dem obigen Skript/Modul?

Was ist das für ein Fehler Can't call method “X” on an undefined value at ${SOMEFILE} line ${SOMELINE} wirklich zu sagen? Bezieht sich dies auf den Kontext des Methodenaufrufs (hier zum Drucken übergeben) oder auf den Kontext der Argumente?

Antwort

6

Diese Syntax sucht nach einem Objekt oder Klassennamen in der Variablen $My::Module und ruft ihre trim-Methode auf, aber diese Variable ist nicht definiert.

Stattdessen möchten Sie nur print My::Module::trim(" \t hello world\t \t"); sagen, um die Funktion My :: Module :: trim() aufzurufen.

Aus der Verwendungszeile sieht es so aus, als ob Sie trim() in das lokale Paket importieren möchten. Sie können es also ohne die My::Module:: Qualifikation aufrufen, aber Ihr Modul sieht nicht so aus, als ob es den Export unterstützt .

In Ihren Regexen haben die Flags/s und/m keinen Effekt - sie ändern nur was.,^Und $ match, und Sie verwenden keines davon.

+0

Ich neige dazu, diese beim Schreiben von Regex zu setzen, weil ich gerne Kommentare inline :). Ich habe nur vergessen, sie aus Gründen des Beispiels herauszunehmen. – heymatthew

+1

@Deemons Advocate,/s und/m haben nichts mit Inline-Kommentaren zu tun. Das ist/x. – cjm

-1

Es ist nur, wie Perl OO macht. Der Unterschied liegt zwischen der Art, wie Sie die Methoden aufrufen.

Dies erfordert nur die Einstellteilanlage im My :: Module Paket:

My::Module::trim('foo') 

Auf der anderen Seite,

My::Module->trim('foo) 

automatisch ein Aufruf an die Einstellteilanlage im My wird :: Modulpaket mit dem String "My :: Module" als erstes Argument. Objekte funktionieren auf die gleiche Art und Weise:

my $m = My::Module->new; # Corrected. Thanks for pointing this out. 
$m->trim('foo'); 

einen Aufruf den gleichen Unter verwandelt sich in, aber diesmal mit einem Verweise auf das $ m Objekt als erstes Argument.

Was Sie versuchen zu tun ist:

$My::Module->trim('foo'); 

, die zu einer dereferenzieren der Variablen $ My :: Module (was nicht vorhanden ist) übersetzt, so dass die Fehlermeldung „Can not Methode X aufrufen auf einen undefinierten Wert ". Wenn $ My :: Module eine tatsächliche Referenz auf ein Objekt wäre, würde dies zu einem Aufruf von trim() für dieses Objekt führen, mit der Referenz als implizitem ersten Argument.

Edit: Beide Kommentatoren sind richtig. Diese Antwort war ursprünglich als Kommentar zur angenommenen Antwort gedacht. (Gibt es eine Möglichkeit, das zu beheben?)

Sorry für die Verwirrung. Ich habe hier ein wenig mehr Details hinzugefügt, also wird es hoffentlich klarer, wie es sich auf die ursprüngliche Frage bezieht (Dereferenzierung einer undefinierten Variable).

+1

Sie sollten die indirekte Methodensyntax für Ihre 'neue' Zeile nicht verwenden. Sehen Sie hier, warum: http://stackoverflow.com/questions/429657/what-is-the-difference-between-new-someclass-and-someclass-new-in-perl/429798#429798 – friedo

+0

Die Informationen in diesem Beitrag ist wahr, aber es hat wirklich nichts mit der Frage zu tun. – jrockway

13

Sie verbinden verschiedene Methoden, um Module und Objekte zu bearbeiten - und enden mit einer, die nicht funktioniert.

Hier sind vier Ansätze, die Arbeit zu tun:

1/My :: Module ist eine Bibliothek. Trim wird nicht exportiert.

$ cat My/Module.pm 
package My::Module; 

use strict; 
use warnings; 

sub trim { 
    my $str = shift; 

    $str =~ s{ \A \s+ }{}xms; # remove space from front of string 
    $str =~ s{ \s+ \z }{}xms; # remove space from end of string 
    return $str; 
} 

1; 
$ cat test 
#!/usr/bin/perl 

use strict; 
use warnings; 

use My::Module; 

# Note: No $ and :: not -> 
print My::Module::trim(" \t hello world\t \t"); 

2/Mein :: Modul ist eine Bibliothek. Trimm wird exportiert.

$ cat My/Module.pm 
package My::Module; 

use strict; 
use warnings; 

use Exporter; 
our @ISA = qw(Exporter); 
our @EXPORT = qw(trim); 

sub trim { 
    my $str = shift; 

    $str =~ s{ \A \s+ }{}xms; # remove space from front of string 
    $str =~ s{ \s+ \z }{}xms; # remove space from end of string 
    return $str; 
} 

1; 
$ cat test 
#!/usr/bin/perl 

use strict; 
use warnings; 

use My::Module; 

print trim(" \t hello world\t \t"); 

3/MyModule ist eine Klasse. trimmen ist eine Klassenmethode.

$ cat My/Module.pm 
package My::Module; 

use strict; 
use warnings; 

sub trim { 
    # Note class name passed as first argument 
    my $class = shift; 
    my $str = shift; 

    $str =~ s{ \A \s+ }{}xms; # remove space from front of string 
    $str =~ s{ \s+ \z }{}xms; # remove space from end of string 
    return $str; 
} 

1; 
$ cat test 
#!/usr/bin/perl 

use strict; 
use warnings; 

use My::Module; 

# Note: Not $ and -> not :: 
print My::Module->trim(" \t hello world\t \t"); 

4/MyModule ist eine Klasse, trim ist eine Objektmethode.

$ cat My/Module.pm 
package My::Module; 

use strict; 
use warnings; 

# Need a constructor (but this one does nothing useful) 
sub new { 
    my $class = shift; 

    return bless {}, $class; 
} 

sub trim { 
    # Note: Object method is passed an object (which is ignored here) 
    my $self = shift; 
    my $str = shift; 

    $str =~ s{ \A \s+ }{}xms; # remove space from front of string 
    $str =~ s{ \s+ \z }{}xms; # remove space from end of string 
    return $str; 
} 

1; 
$ cat test 
#!/usr/bin/perl 

use strict; 
use warnings; 

use My::Module; 

my $trimmer = My::Module->new; 

print $trimmer->trim(" \t hello world\t \t"); 

Ich denke, dass Sie für die Option 1. In diesem Fall versucht wurden, glaube ich Option würde empfehlen, 2.

Und Ihre letzte Frage zu beantworten. Sie erhalten diesen Fehler, weil Sie versuchen, eine Methode für eine Variable ($ My :: Module) aufzurufen, die nicht definiert ist.

Verwandte Themen