2015-12-11 21 views
0

有這個演示CGI腳本(cgi_script.pl如何繼承CGI.pm以充分實用?

use 5.014; 
use warnings; 
use CGI; 
my $q = CGI->new(); 
say $q->h1(join '-', $q->multi_param('p')); 
say CGI::h1('some other'); 

乳寧它作爲perl cgi_script.pl p=1 p=2打印

<h1>1-2</h1> 
<h1>some other</h1> 

我想創建My::CGICGI做它應該做的每一件事。現在我有:

package My::CGI; 
use 5.014; 
use warnings; 
use base qw(CGI); 
1; 

並修改上面的腳本(my_script.pl

use 5.014; 
use warnings; 
use My::CGI; 

my $q = My::CGI->new(); 
say $q->h1(join '-', $q->multi_param('p')); 
say My::CGI::h1('some other'); 

運行它作爲perl my_script.pl p=1 p=2當它打印:

<h1>1-2</h1> 
Undefined subroutine &My::CGI::h1 called at my_script.pl line 7. 

例如,面向對象接口的工作原理,但不是功能,如CGI::h1(...)等。

現在的問題是:如何創建My::CGI與父母CGI完全兼容?例如

  • 以獲得工作功能接口,例如, My::CGI::h1(...) ... etc
  • 並且還從CGI得到工作use My::CGI qw(:xxx) #xxx,例如, :all:html2等..

不是需要編寫代碼,只是任何指針/理念,以「如何正確解決」的問題。

+0

混合模式(OO +功能)模塊的接口都在Perl社區失寵,而現在,你看到的原因之一。要將OO模塊的功能接口「繼承」到您的子類中,您需要完全接受命名空間污染。 – tjd

回答

3

幸運的是,CGI支持:all標籤:

#! /usr/bin/perl 
use warnings; 
use strict; 

{ package MyCGI; 
    use CGI qw{ :all }; # Import all functions. 
    use parent 'CGI'; # Inherit the methods. 
} 

my $q = MyCGI->new; 
print $q->h1('Title'); 
print MyCGI::h2('Section'); 
+0

是的!太好了謝謝。 – Nemo

+0

顯然這是較短的版本。 :) – simbabque

1

你基本上給出了答案的基礎。你在談論sub_classing_。 A 意味着對象。調用提供功能和麪向對象接口的模塊的功能接口在繼承時需要額外的工作。

Perl的面向對象有幾個缺陷。通常它可以與包名稱空間一起使用。有CGI,有My::CGI。如果你說

package My::CGI; 
use base 'CGI'; 

package My::CGI; 
use parent 'CGI'; 

你告訴Perl被祝福到我:: CGI命名空間中任何有CGI在其@ISA。這是繼承的東西。

但是,如果您調用一個簡單的函數(而不是方法),那麼將被忽略。只有命名空間。

package My::CGI; 
use 5.014; 
use warnings; 
use base qw(CGI); 
1; 

此包未在其名稱空間中定義任何子項。所以你不能打電話給他們。它們仍然只位於CGI包中。

你會先把它們放到你自己的命名空間中。

package My::CGI; 
use 5.014; 
use warnings; 
use base qw(CGI); 

*h1 = \&CGI::h1; 

1; 

現在你的示例調用將起作用。

當然這有點乏味。您可以查看符號表,查看條目並與那些條目一起工作,以自動爲所有功能接口子接口創建別名。

+0

所以,如果我理解正確 - 基本上需要別名'* sub'所有在[CGI.pm](https://metacpan.org/source/LEEJO/CGI-4.22/lib/CGI.pm)中的函數' s'%EXPORT_TAGS'。可能需要創建我自己的EXPORT。 – Nemo

+0

@Nemo是的,就是這麼多。 – simbabque