2014-04-14 84 views
1

我有這樣的父模塊MyApp.pm:Perl的出口子模塊

package MyApp; 
use Moose; 
use base 'Exporter'; 
our @EXPORT = qw(msg); 
sub msg { 
    print "Hello msg\n"; 
} 
1; 

並通過該子模塊MyApp2.pm繼承:

package MyApp2; 
use Moose; 
extends qw(MyApp); 
1; 

,當在App.cgi使用這樣的腳本:

#!/usr/bin/perl 
use MyApp2; 
msg(); 

我收到錯誤消息:

Undefined subroutine &main::msg called at App.cgi line 3. 

因此,導出的函數在子類MyApp2中不起作用,但只有在使用「使用MyApp」而不是「使用MyApp2」時才起作用。我假設導出的函數應該可以訪問擴展父類的子模塊。我做錯了什麼。

回答

0

這裏是我找到了我的請求,解決方案:

package MyApp; 
use Moose; 
use base 'Exporter'; 
our @EXPORT = qw(msg); 

sub import { 
my ($class, @args) = @_; 
    my $caller = $class.'::'; 
    { 
     no strict 'refs'; 
     @{$caller.'EXPORT'} = @EXPORT; 
     foreach my $sub (@EXPORT) { 
      next if (*{"$caller$sub"}{CODE}); 
      *{"$caller$sub"} = \*{$sub}; 
     } 
    } 
    goto &Exporter::import; 
} 

sub msg { 
    print "Hello msg MyApp\n"; 
} 
1; 

這裏的想法是我的「@EXPORT」陣列中的所有內容導出到子模塊,只添加無存在的潛艇所以不會覆蓋子類中的任何方法。

在上面的這個例子中,這個從MyApp導出到子MyApp2。

這適用於我自己的需求。

5

繼承只改變方法調用的處理方式;函數調用或變量訪問(如our @EXPORT)不受影響。

相反導出功能,你可以使用它作爲一個方法:

use MyApp2; 

MyApp2->msg; 

,但在這種情況下,這將是更清潔,以便導入msg功能顯式地加載MyApp,並額外負載MyApp2爲了加載這個類。

use MyApp; 
use MyApp2; 

msg; 

通常建議一個模塊既可以面向對象或提供經由導出的函數的接口,但不能兩者都做。

+0

所以沒有辦法導出到子模塊?我想用一個主模塊構建我自己的小框架,並且所有子模塊擴展此模塊,以便所有應用程序共享相同的環境,我想要做的是在主模塊中導出功能,並可供所有子模塊使用。那可能嗎? – daliaessam

+2

這是可能的 - 而不是'擴展qw(MyApp);'寫'使用MyApp;擴展qw(MyApp);'。儘管如此,這非常非常不可取。除非你足夠上師,否則這種事情可能會讓你繼續走下去。任何需要問及如何做到這一點的人都不夠上師。 – tobyink