2011-05-24 24 views
10

說我有一個名爲My::Pkg包,該包具有->new(...)類方法來實例化新的對象:在Perl中,創建一個與程序包同名的子程序會有什麼壞處嗎?

package My::Pkg; 

sub new {bless {@_[1..$#_]} => $_[0]} 

是否有定義以下子程序任何傷害:

sub My::Pkg {@_ ? My::Pkg::new('My::Pkg', @_) : 'My::Pkg'} 

,從而使他人可以這樣寫:

my $obj = My::Pkg one => 1, two => 2; 

不是:

my $obj = My::Pkg->new(one => 1, two => 2); # which still works, but is longer 

我喜歡的包,命名構造子程序方法的簡潔性,但我想知道是否有任何隱藏的陷阱這一技術,我都沒有想到的。


更新:

繼承正常工作,如通過這裏的例子:

{package a; sub new {say "a::new [@_] ", $_[0]->init}} 
{package b; our @ISA = 'a'; sub init {"(b::init [@_])"}} 
{package a::b; our @ISA = 'b';} 

sub a::b {print "absub [@_], "; 'a::b'} 

# a::b() called with no args, returns 'a::b', which then becomes 'a::b'->new(...) 
a::b->new;   # absub [], a::new [a::b] (b::init [a::b]) 
a::b->new(1, 2, 3); # absub [], a::new [a::b 1 2 3] (b::init [a::b])  

# no call to `a::b()` but otherwise the same: 
'a::b'->new;   # a::new [a::b] (b::init [a::b]) 
'a::b'->new(1, 2, 3); # a::new [a::b 1 2 3] (b::init [a::b]) 

new a::b::;   # a::new [a::b] (b::init [a::b]) 
new a::b:: 1, 2, 3; # a::new [a::b 1 2 3] (b::init [a::b]) 

有趣的是,唯一的事情,到目前爲止這是不同的是,下面的2線變得語法錯誤:

new a::b; 
new a::b 1, 2, 3; 

由於同樣的原因,這是一種語法錯誤some_undefined_sub some_defined_sub;就是其中之一。

如果定義了new子例程,則將其解析爲new(a::b(...)),這對於兩個相鄰的空白子例程是正常的。

就個人而言,我行與new a::b成爲一個語法錯誤,明確的版本new a::b::將永遠正常運行tchrist有益下面指出。

+0

似乎乾淨。如果某件事失敗了,它會是'some_sub My :: Pkg a => 1,b => 2;'。它沒有。 – ikegami 2011-05-24 21:22:09

+0

@ikegami:這肯定** ** DOES失敗:'子X ::Ÿ{死 「X :: Y()稱爲\ n」} 子X ::Ÿ::新{警告「X ::ÿ ::新()稱爲\ n」} 子新{死 「主要::新()被稱爲」} $ A =新的X :: Y 「業務」; 警告 「得到$了」;'會的正確調用'X死,因爲它調用'主::新的(X :: Y( 「企業」))'作爲一個子程序,而不是::Ÿ::新(「X: :Y「,」business「))'作爲一種方法。此外,該子程序調用並不尊重繼承,這在OO世界中被認爲是強制性的。 – tchrist 2011-05-24 22:40:14

+0

它是邪惡的'新X :: Y 「業務」'突然意味着什麼不同'X :: Y->新的( 「企業」)' - *,其中* BTW現在實際上是指'X :: Y() - > new(「business」)'而不是所有人都認爲它意味着的'X :: Y :: new(「X :: Y」,「business」)''。 – tchrist 2011-05-24 22:53:33

回答

7

這是正是爲什麼

$thingie = new Some::Class one => 1, two => 2; 

$thingie = new Some::Class:: 
       one => 1, 
       two => 2, 
      ; 

存在,所以才使用。

但是,我認爲你會陷入一大堆麻煩,因爲我是世界上唯一一個不願意打包報價的人。我現在沒有時間去挖掘我的舊問題測試代碼,但我很肯定,如果你走上講話的道路,這最終會讓你哭泣。

+0

我會認爲間接對象語法會導致比這種技術更多的歧義。使用這種方法,標識符'My :: Pkg'總是指'&My :: Pkg()',除非它在全局上下文中,它是字符串。我有興趣知道任何不適用的情況。 – 2011-05-24 20:32:50

+0

調用方法和調用子例程的方法之間存在巨大差異:**繼承**。通過不使用方法調用,你打破了OO設計。 Perl有各種奇怪的東西,所以'Some :: Class'真的意味着''Some :: Class'',這就是人們期待它做的事情。如果你通過包的名字創建一個函數,當你試圖進行類方法調用時,你會完全壓縮自己,因爲你會調用dumb函數。與流行的貨物邪教神話相反,「METHOD CLASS :: ARGLIST」絕對沒有任何含糊之處。 – tchrist 2011-05-24 22:28:51

+0

查看上面問題的更新,繼承工作正常。 – 2011-05-25 01:58:07

4

「我很想知道是否有任何隱藏的技巧,我沒有想到。」

我認爲隱藏的疑難雜症與大多數OOP lang定義構造函數的方式缺乏一致性。很顯然,Perl喜歡它的TMTOWTDI哲學,但是如果你不在身邊/有時候需要維護代碼的人可能需要更多時間來理解你的代碼在做什麼。

另外,如果你想添加另一個構造函數呢?我見過一些類,其中有構造函數名爲new,new_from_file等。也許不是最好的設計,但它確實闡明瞭一個對象是以獨特的方式構造的。

相關問題