2012-09-25 106 views
3

如何将函数传递给构造函数,以便类可以在内部使用它?如何将函数传递给构造函数

test.pl

use Class; 
use Loger; 

my $loger = Loger->new(); 
$loger->log('I have logger now, I can log messages!'); 

my $class = Class->new(\&{ $loger->log }); # here we pass the function (the method of other class) to contructor of a new Class 

$class->do_something(); # class uses loger->log internally to report errors 

Class.pm 类,包;

sub new { 

    my $self = {}; 
    $self->{log} = shift; # we got logger->log function, save it for future use 

    return bless $self; 
} 

sub do_something { 
    my $self = shift; 

    open_file or $self->{log}->('Cant open file'); # we can use gotten logger in class 
} 


1; 
+0

你可能要考虑使用这样的单例模式:http://perldesignpatterns.com/?SingletonPattern。每个需要使用记录器的课程可以调用例如Logger :: getLogger()(或只是Logger-> new()),而不是将其作为构造函数参数。 – RobEarl

回答

3

你快到了。

虽然$loger->log是函数调用,但您可以使用\&Loger::log来引用该函数。

\&{ref($loger)."::log"}也可能工作。

合并@simbabques点,你应该在你的函数通过之前咖喱,即预先提供第一个参数。您可以通过调用构造与

sub {$loger->log(@_)} 

sub {unshift @_, $loger; goto \&Loger::log} # more efficient 

作为参数做到这一点。

+2

'sub {$ loger-> log(@_)}'示例创建一个闭包,对吧?第二个是奇怪的,看起来不应该在生产代码中使用,没有严格的评论。 – simbabque

+0

@simbabque是的,都是关闭(所有的子都是),第二个违反OOP('Loger'不能是子类)。但它具有节省一点存储空间的优点,并且由于(goto)(恶)转而运行速度快两倍,并且方法分辨率被跳过;-) – amon

+0

这种'goto'并不像其他类型那样邪恶。;-) – simbabque

3

您试图传递一个方法,而不是函数(或子)。自己调用它不起作用。如果你想要一个对象的方法,传递该对象并调用该对象的方法。

my $loger = Loger->new(); 
$loger->log('I have logger now, I can log messages!'); 

my $class = Class->new(logger => $loger); # pass the Loger object 

而且在Class.pm

package Class; 

sub new 
{ 
    my ($class, %args) = @_; 
    my $self = {}; 
    $self->{log} = $args{'logger'}; # store it inside your Class object 
    return bless $self; 
} 

sub do_something 
{ 
    my $self = shift; 
    open_file or $self->{log}->log->('Cant open file'); # call its log-method 
} 
+0

谢谢,我知道这种方式,但“$ self - > {log} - > log - >('不能打开文件')”看起来很丑陋 – xoid

+0

@xoid,然后将它抽象出来!编写一个'$ self-> log()'方法来调用'$ self - > {log} - > log()',或者如果'$ self - > {log}'不是有效的记录仪。 – pilcrow

+0

@xoid:@pilcow说了些什么,并将它存储在'$ self - > {'LoggerInstance'}'或类似的文件中,以便它更具自选性。 – simbabque

0

\引用运营商只能在指定符号。

你行:

my $class = Class->new(\&{ $loger->log });

实际上是传递一个匿名子程序的尝试。它也缺少一种将参数传递给$ loger-> log()的方法。

你可以把它改成部份:

my $class = Class->new(sub { $loger->log(@_) });

相关问题