2013-04-17 26 views
0

我試圖在子類中創建一個超類泛型方法的別名,但它似乎沒有工作。這個竅門在同一個類中是有效的,但它似乎不適用於超級/子級轉換。這是一個真正的基本示例。前兩個電話工作。第三次調用會產生關於未定義的子例程的錯誤。我也試過使用SUPER :: cat,但那也沒用。Perl - 如何在子類中創建方法別名?

package foo; 

sub cat{ 
    print("inside foo\n"); 
} 

*bird = \&cat; 

package bar; 

use base 'foo'; 

*dog = \&cat; 

package main; 

foo::cat(); 
foo::bird(); 
bar::dog(); 

回答

3

此:

*dog = \&cat; 

應該是:

*dog = \&foo::cat; 
+0

這的確行得通。我只是不清楚爲什麼我需要它。 「use base」不應該將所有父級方法導入到我的子級中嗎? –

+1

「use base」與基類建立ISA關係 –

5

你是面向對象的繼承和簡單的符號進口之間混淆。

正如你所說use base 'foo'宣佈超級類。這意味着將檢查foo是否有任何對bar中未出現的方法的調用。

*dog = \&cat不是一個方法調用:它只是一個glob賦值,所以搜索不會超出&bar::cat

如果您正在編寫真正的面向對象的代碼,那麼像*bar::dog那樣分配將破壞繼承機制的重點。

要觀察Perl的面向對象的功能,請將glob賦值移至foo(它只是簡單地對一個方法進行別名)並使用方法調用語法進行調用。

在這段代碼,bar沒有自己的方法和繼承一切foo,但該代碼按預期工作。

package foo; 

sub cat { 
    print("inside foo\n"); 
} 

*bird = \&cat; 
*dog = \&cat; 


package bar; 

use base 'foo'; 



package main; 

bar->cat(); 
bar->bird(); 
bar->dog(); 

輸出

inside foo 
inside foo 
inside foo 
+0

+1:我的評論成了它自己的答案:http://stackoverflow.com/a/16070397/468327 –

2

你應該寫

sub dog { shift->cat(@_) } 

(基本上ETA-轉換cat方法),而不是使用水珠分配,使得bar子類可以覆蓋或延長cat而不破壞bar的合同catdog做同樣的事情。

+0

嗯,是的,這比我的更容易閱讀: - / –

1

考慮到這些想法,鮑羅丁已經提出了一個更進一步的假設,你正在做適當的面向對象,但確實想要一個由父類提供的方法的別名,並且只能在這個子類(以及更深)中使用。在這種情況下,您可能需要:

#!/usr/bin/env perl 

package foo; 

sub new { return bless {}, shift } 

sub cat{ 
    print("inside foo\n"); 
} 

*bird = \&cat; 

package bar; 

use base 'foo'; 

sub dog { $_[0]->can('cat')->(@_) } 

package main; 

my $bar = bar->new; 
$bar->cat(); 
$bar->bird(); 
$bar->dog(); 

此機制在堆棧跟蹤中保留dog。如果你不想這樣做,你可以使用goto &sub表單,但是如果你知道爲什麼,你應該這樣做,我不打算在這裏舉個例子。