2009-01-09 142 views
27

很多年前,我記得有一個傢伙程序員輔導這樣的:Perl中的新Some :: Class和Some :: Class-> new()有什麼區別?

new Some::Class; # bad! (but why?) 

Some::Class->new(); # good! 

可悲的是,現在我不記得/他的原因。 :(即使構造函數實際上不存在於Some :: Class模塊中,但兩種形式都能正常工作,而是從某處父級繼承。

這兩種形式都與Some :: Class :: new (),它不會將類的名稱作爲第一個參數傳遞給構造函數 - 所以這個表單總是不正確的

即使這兩種形式是等價的,我發現Some :: Class-> new )更加清晰,因爲它遵循調用模塊方法的標準約定,而在perl中,'new'方法並不特殊 - 構造函數可以被調用任何東西,而new()可以做任何事情(儘管當然我們一般都會期望它是一個構造函數)

+0

另一個很好的參考:[間接但仍然致命](http://www.shadowcat.co.uk/blog/matt-s-trout/indirect-but-still-fatal/) – Ether 2010-06-22 20:49:21

回答

26

使用new Some::Class被稱爲「間接」方法調用,並且它很糟糕,因爲它在語法中引入了一些模糊性。

它可以失敗的一個原因是如果你有一個數組或散列的對象。你可能期望

dosomethingwith $hashref->{obj} 

等於

$hashref->{obj}->dosomethingwith(); 

但它實際上解析爲:

$hashref->dosomethingwith->{obj} 

這可能不是你想要的。

另一個問題是,如果在你的軟件包中碰巧有一個函數與你試圖調用的方法具有相同的名稱。例如,如果某個模塊use'd導出了一個名爲dosomethingwith的函數?在這種情況下,dosomethingwith $object含糊不清,並可能導致令人困惑的錯誤。

使用->語法專門消除了這些問題,因爲該方法以及您希望該方法操作的內容對編譯器而言始終是清楚的。

21

請參閱Indirect Object Syntax在perlobj文檔中解釋其缺陷。 freido's answer涵蓋其中一個(儘管我傾向於避免與我的函數調用顯式parens)。

拉里曾經開玩笑說,它讓C++對new感到高興,儘管人們會告訴你永遠不要使用它,但你可能一直在做。考慮這個:

print FH "Some message"; 

你有沒有想過我的文件句柄後沒有逗號?間接對象​​符號中的類名後面沒有逗號?這就是這裏發生的事情。你可以重寫作爲打印方法調用:

FH->print("Some message"); 

你可能已經經歷了一些古怪的print如果你這樣做是錯誤的。在顯式文件句柄之後加上逗號將其變爲參數:

print FH, "some message";  # GLOB(0xDEADBEEF)some message 

不幸的是,我們在Perl中有這種愚蠢。並非所有融入語法的東西都是最好的想法,但是當你從衆多的靈感中獲取靈感時,會發生這種情況。一些想法必須是不好的。

+7

我還沒有讀過多年的手冊頁;我真的應該閱讀更多。這是一個恥辱'新的Some :: Class'有這麼多的陷阱,因爲我喜歡它的讀法比'Some :: Class-> new()'更好;我最喜歡Perl的一件事情就是自然語言。哦,時候換一下..... – 2009-01-10 06:44:56

4

出於好的理由,間接的對象語法是皺眉,但這與構造函數無關。你幾乎不會在調用包中有一個new()函數。相反,你應該使用套餐的>新()的另外兩個(更好?)原因:

  1. 正如你所說,所有其他類方法的形式是套餐的>()的方法,所以一致性是一個很好的事情

  2. 如果你要爲構造函數提供參數,或者你正在接受構造函數的結果並立即調用它的方法(例如,如果你不關心保持對象的話),這更簡單說例如

$foo = Foo->new(type => 'bar', style => 'baz'); 
Bar->new->do_stuff; 

$foo = new Foo(type => 'bar', style => 'baz'); 
(new Bar)->do_stuff; 
-3

另一個問題是,new Some::Class發生在運行時間。如果出現錯誤,而且您沒有測試此分支的分支,則直到生產時纔會知道它。除非您正在進行動態編程,否則最好使用Some::Class->new

相關問題