0

以下に示すものと同様の Perl コードを継承しました。パッケージには共通のサブルーチンが含まれており、名前空間をインポートまたはエクスポートしません。この呼び出し規約は異例のようです。リファクタリングはオプションです。

現在のパッケージ内でサブルーチンを呼び出すときにパッケージに明示的に名前を付けることのリスク/副作用を理解することに興味があります。前もって感謝します。

package Util;
sub _step1 {
    # <code>
}
sub _step2 {
    # <code>
}
sub doWork {
   Util::_step1();
   Util::_step2();
}
1;
4

2 に答える 2

3

面白い。これが継承にどのように影響するかを考えています。

andメソッドUtilをオーバーライドするクラスの子クラスを想像してください。そのクラスがメソッドを呼び出した場合。子クラスとメソッドを呼び出すのではなく、親クラスとメソッドを呼び出します。_step1_step2dowork_step1_step2_step1_step2

補遺

関数呼び出しは継承を無視します。モジュールは、継承を問題にするために Util->_step1() またはpackage ->_step1() のようなことをする必要があり、それでもパッケージ検索は子クラスではなく Util で始まります。– ヴェンタツ

本当に?テストするのに十分簡単に​​思えます。

私は 2 つのパッケージを持っています:Local::UtilLocal::Util::Child私のプログラムで定義されています。Local::Util::Child は の子クラスですLocal::Util

クラスLocal::Utilには、次のコンストラクターとメソッドが定義されています。

  • new: そのクラスの新しいオブジェクトを作成します
  • _step1
  • _step2
  • doWork: これはプレフィックス付きの_step1andを呼び出します。_step2Util::
  • doWork2: これは接頭辞なしで_step1呼び出します。_step2Util::
  • doWork3: これはプレフィックス付きの_step1andを呼び出します。_step2__PACKAGE__
  • doWork4: これは、 から取得した接頭辞を付けて呼び出さ_step1_step2まし$classref

クラスはメソッドをLocal::Util::Child再定義するだけです。_step2

プログラムは次のとおりです。

#! /usr/bin/env perl
#
use strict;
use warnings;
use feature qw(say);

# This is our basic Local::Util object manipulation

my $util_obj = Local::Util->new;
say q("$util_obj" is a member of the ") . ref($util_obj) . q(" class);

print q($util_obj->_step1: );
$util_obj->_step1;

print q($util_obj->_step2: );
$util_obj->_step2;

# This is a child class object of the above

my $uc_obj = Local::Util::Child->new;
say q("$uc_obj" is a member of the ") . ref($uc_obj) . q(" class);

# Calls to straight forward methods

print q($uc_obj->_step1: );
$uc_obj->_step1;

print q($uc_obj->_step2: );
$uc_obj->_step2;

# Now calls to methods that call other methods

say qq(\n=====\$util_obj->doWork=====);
$util_obj->doWork;

say qq(\n=====\$uc_obj->doWork=====);
$uc_obj->doWork;

say qq(\n=====\$util_obj->doWork2=====);
$util_obj->doWork2;

say qq(\n=====\$uc_obj->doWork2=====);
$uc_obj->doWork2;

say qq(\n=====\$util_obj->doWork3=====);
$util_obj->doWork3;

say qq(\n=====\$uc_obj->doWork3=====);
$uc_obj->doWork3;

say qq(\n=====\$util_obj->doWork4=====);
$util_obj->doWork4;

say qq(\n=====\$uc_obj->doWork4=====);
$uc_obj->doWork4;

###################################################
# Package Local::Util
#
package Local::Util;

sub new {
    my $class = shift;
    my $self = {};
    bless $self, $class;
}

sub _step1 {
    say "I'm calling Local::Util::_step1";
}

sub _step2 {
    say "I'm calling Local::Util::_step2";
}

sub doWork {
    Local::Util::_step1();
    Local::Util::_step2();
}

sub doWork2 {
    _step1();
    _step2();
}

sub doWork3 {
    __PACKAGE__->_step1();
    __PACKAGE__->_step2();
}

sub doWork4 {
    my $self = shift;
    my $class = ref $self;

    $class->_step1();
    $class->_step2();
}
#
#############################################

#############################################
# Package Local::Util::Child
#

package Local::Util::Child;
use base qw(Local::Util);

sub _step2 {
    say "I'm calling Local::Util::Child::_step2";
}

そして、ここに出力があります:

"$util_obj" is a member of the "Local::Util" class
$util_obj->_step1: I'm calling Local::Util::_step1
$util_obj->_step2: I'm calling Local::Util::_step2
"$uc_obj" is a member of the "Local::Util::Child" class
$uc_obj->_step1: I'm calling Local::Util::_step1
$uc_obj->_step2: I'm calling Local::Util::Child::_step2

=====$util_obj->doWork=====
I'm calling Local::Util::_step1
I'm calling Local::Util::_step2

=====$uc_obj->doWork=====
I'm calling Local::Util::_step1
I'm calling Local::Util::_step2

=====$util_obj->doWork2=====
I'm calling Local::Util::_step1
I'm calling Local::Util::_step2

=====$uc_obj->doWork2=====
I'm calling Local::Util::_step1
I'm calling Local::Util::_step2

=====$util_obj->doWork3=====
I'm calling Local::Util::_step1
I'm calling Local::Util::_step2

=====$uc_obj->doWork3=====
I'm calling Local::Util::_step1
I'm calling Local::Util::_step2

=====$util_obj->doWork4=====
I'm calling Local::Util::_step1
I'm calling Local::Util::_step2

=====$uc_obj->doWork4=====
I'm calling Local::Util::_step1
I'm calling Local::Util::Child::_step2

面白い。プレフィックスを付けるかどうかにUtil::関係なく、子のメソッドではなく親メソッドを呼び出します。プレフィックス__PACKAGE__を付けても同じことが起こります (現在のクラスの定義を呼び出していることを確認するために、どのように行うべきかを考えました)。子を機能させる唯一の方法は、コマンド$classから取得する必要があったプレフィックスを使用することです。ref

したがって、別のメソッドでメソッドを呼び出すと、子のメソッドではなく、そのクラスのメソッドがデフォルトになるようです。これは理にかなっていると思います-特に、親メソッドの外部からアクセスしてはならないプライベートメソッドのよう_step1に見えるためです。_step2

于 2012-04-19T02:11:59.783 に答える
0

それはいいです。唯一の欠点は、モジュールの名前を変更すると、サブ呼び出しの名前を変更するのを忘れる可能性があることです。

しかし、やりたいと思うのは奇妙なことです。これを行いたい理由を教えていただければ、より良い方法を提供できるかもしれません。

于 2012-04-19T19:05:16.873 に答える