12

オブジェクトに対するCGI::ApplicationのアクセサーがどのようにCGI呼び出されるかが嫌いqueryです。

インスタンスクラスが、サブクラスの現在のインスタンスに関連付けcgiられたオブジェクトを取得するために指定されたアクセサを使用できるようにしたいと思います。CGICGI::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メソッド名をエイリアシングする目的で使用することの長所/短所は何ですか?もっと良い方法はありますか?

注: Perlのこの使用法は、あなたが考えているものとは異なるため、goto悪意を持って対応したい場合は、それを行わないでください。goto

4

4 に答える 4

10

/などが適切に機能し続けるgotoことが保証されるため、のアプローチは正しいものです。callerwantarray

次のように新しいメソッドを設定します。

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の割り当てが継承に反する場合がいくつかあるため、疑わしい場合は、最初のメソッド(サブパッケージに新しいメソッドを作成する)を使用してください。

Michael Carmanは、両方の手法を組み合わせて自己再定義関数にすることを提案しました。

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'";
}
于 2010-02-15T16:54:47.590 に答える
3

シンボルテーブルを操作することにより、サブルーチンのエイリアスを作成できます。

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

いくつかの例はここにあります。

于 2010-02-15T15:30:58.387 に答える
2

正しい方法はわかりませんが、AdamKennedyはMethod:: Aliasgotoで2番目のメソッド(つまり、なし)を使用しています(ソースコードに直接移動するには、ここをクリックしてください)。

于 2010-02-15T17:53:47.830 に答える
1

これは、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分子が示唆するように、はメソッドを指定する適切な方法かもしれません。

ただし、親と子の両方のカテゴリを制御する、かなり適切に制御されたライブラリである場合、上記の方法はよりスリムになります。

于 2010-02-15T21:01:07.577 に答える