2010-08-30 50 views
6

所有的地方,尤其是在DBI,我看到這條消息來了所有的時間。這很令人困惑,因爲首先想到的是我傳遞函數的參數設置爲undef(或類似的),但顯然不是這種情況。

給定一個模塊和相應的腳本...

模塊:./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; 
} 

腳本:./test.pl

#!/usr/bin/perl 

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

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

我找回了錯誤信息

鈣不要在「./text.pl」第7行的未定義值處調用方法「trim」。

事實上,如果我撥打$My::Module->notamethod("hello world");,它會給出類似的錯誤。

出了什麼問題上面的腳本/模塊?

那是什麼錯誤Can't call method 「X」 on an undefined value at ${SOMEFILE} line ${SOMELINE}真的說什麼? 這是指這個方法調用的上下文(傳給這裏打印)還是參數的上下文?

回答

6

即語法正在尋找在變量$My::Module對象或類名和調用其修剪的方法,但該變量是未定義的。

相反,你只想說print My::Module::trim(" \t hello world\t \t");打電話給我::模塊:: TRIM()函數。

從使用線看,您正在嘗試將trim()導入到本地包中,因此您可以在沒有My::Module::限定條件的情況下調用它,但是您的模塊看起來並不像支持導出。

在你的正則表達式中,/ s和/ M標誌沒有任何影響 - 他們只改一下,^和$匹配,並且不使用任何這些的。

+0

我傾向於把這些寫在正則表達式的,因爲我喜歡把評論內聯:)。我只是爲了舉例而忘了帶他們出去。 – heymatthew 2010-08-30 03:38:05

+1

@ The Daemons Advocate,/ s和/ m與內嵌評論無關。那是/ x。 – cjm 2010-08-30 05:48:43

-1

這正是Perl如何做OO。區別在於你調用方法的方式。

這只是調用在我的Trim子::模塊封裝:

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

在另一方面,

My::Module->trim('foo) 

自動變得對我修剪子打電話::作爲第一個參數的模塊包含字符串「My :: Module」。 對象的工作方式相同:

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

打開到相同的子打電話,但這次與參考$ M對象作爲第一個參數。

你所要做的是:

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

它轉換爲變量$我::模塊(不存在),因此,錯誤消息「無法調用X的反引用在一個未定義的值「。如果$ My :: Module是一個對象的實際引用,這將導致對該對象的trim()調用,引用爲隱式的第一個參數。

編輯:這兩位評論者都是正確的。這個答案最初是作爲對接受答案的評論。 (有沒有辦法解決這個問題?)

對不起,混淆。我在這裏添加了更多的細節,希望它能更清楚地說明它與原始問題的關係(取消引用未定義的變量)。

+1

您不應該在'new'行中使用間接方法語法。看到這裏爲什麼:http://stackoverflow.com/questions/429657/what-is-the-difference-between-new-someclass-and-someclass-new-in-perl/429798#429798 – friedo 2010-08-30 04:20:39

+0

本文中的信息是真的,但它與這個問題沒有任何關係。 – jrockway 2010-08-30 06:07:23

13

你正在混合幾種不同的方式來處理模塊和對象 - 最後一個不起作用。

這裏是做工作的四種方法:

1 /我::模塊是一個圖書館。修剪不會導出。

$ 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/My :: Module是一個庫。修剪被導出。

$ 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是一個類。修剪是一種類方法。

$ 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是一個類,trim是一個對象方法。

$ 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"); 

我認爲你試圖爲選項1.在這種情況下,我想我會建議選擇2

並回答你的最後一個問題。你正在得到那個錯誤,因爲你試圖調用一個未定義的變量($ My :: Module)的方法。

相關問題