代码之家  ›  专栏  ›  技术社区  ›  Sinan Ünür

在Perl中,子类在基类中别名方法的正确方法是什么?

  •  12
  • Sinan Ünür  · 技术社区  · 14 年前

    CGI::Application 的访问器 CGI 对象被调用 query .

    cgi 得到 CGI::Application 子类。

    下面是我正在做的一个独立的例子:

    package My::Hello;
    
    sub hello {
        my $self =shift;
        print "Hello @_\n";
    }
    
    package My::Merhaba;
    
    use base 'My::Hello';
    
    sub merhaba {
        goto sub { shift->hello(@_) };
    }
    
    package main;
    
    My::Merhaba->merhaba('StackOverflow');
    

    这是工作,因为我认为它应该,我看不到任何问题(例如,如果我想继承 My::Merhaba :子类不需要知道关于 merhaba ).

    写得更好/更正确吗

    sub merhaba {
        my $self = shift;
        return $self->hello(@_);
    }
    

    goto &NAME 为了给方法名添加别名?有更好的办法吗?

    如果你有强烈的欲望去回应 goto 是邪恶的 不要这样做,因为这样使用Perl 后藤 与你的想法不同。

    4 回复  |  直到 14 年前
        1
  •  10
  •   Eric Strom    14 年前

    你的方法 goto 是正确的,因为它将确保 caller / wantarray

    我会像这样设置新方法:

    sub merhaba {
        if (my $method = eval {$_[0]->can('hello')}) {
            goto &$method
        } else { 
            # error code here
        }
    }
    

    或者,如果不想使用继承,可以从调用代码中将新方法添加到现有包中:

    *My::Hello::merhaba = \&My::Hello::hello;  
       # or you can use = My::Hello->can('hello');
    

    然后你可以打电话:

    My::Hello->merhaba('StackOverflow');
    

    并得到了预期的结果。

    无论哪种方法都可以,继承路由更易于维护,但是将方法添加到现有包中会导致更快的方法调用。

    编辑:

    正如评论中所指出的,有一些情况下glob赋值会与继承冲突,因此如果有疑问,请使用第一个方法(在子包中创建一个新方法)。

    sub merhaba {
        if (my $method = eval { $_[0]->can('hello') }) {
            no warnings 'redefine';
            *merhaba = $method;
            goto &merhaba;
        }
        die "Can't make 'merhaba' an alias for 'hello'";
    }
    
        2
  •  3
  •   Eugene Yarmash    14 年前

    通过操纵符号表,可以为子例程设置别名:

    *My::Merhaba::merhaba = \&My::Hello::hello;
    

    可以找到一些例子 here .

        3
  •  2
  •   Christopher Bottoms zerkms    14 年前

    我不确定什么是正确的方法,但亚当·肯尼迪使用了你的第二种方法(即没有 goto Method::Alias ( click here to go directly to the source code ).

        4
  •  1
  •   Axeman maxelost    14 年前

    这是一种Quick-n-Dirty与使用 UNIVERSAL::can

    package My::Merhaba;
    use base 'My::Hello';
    # ...
    *merhaba = __PACKAGE__->can( 'hello' );
    

    在这个包中有一个名为“merhaba”的子包,它有别名 My::Hello::hello hello 可以用这个名字 merhaba .

    但是,这是不够的,因为某些代码装饰程序可能会更改 *My::Hello::hello{CODE} 指向。那么,, Method::Alias 可能是指定方法的合适方式,如分子所示。

    但是,如果它是一个控制良好的库,您可以同时控制父类别和子类别,那么上面的方法是 苗条的 .