面白い。これが継承にどのように影響するかを考えています。
andメソッドUtil
をオーバーライドするクラスの子クラスを想像してください。そのクラスがメソッドを呼び出した場合。子クラスとメソッドを呼び出すのではなく、親クラスとメソッドを呼び出します。_step1
_step2
dowork
_step1
_step2
_step1
_step2
補遺
関数呼び出しは継承を無視します。モジュールは、継承を問題にするために Util->_step1() またはpackage ->_step1() のようなことをする必要があり、それでもパッケージ検索は子クラスではなく Util で始まります。– ヴェンタツ
本当に?テストするのに十分簡単に思えます。
私は 2 つのパッケージを持っています:Local::Util
とLocal::Util::Child
私のプログラムで定義されています。Local::Util::Child は の子クラスですLocal::Util
。
クラスLocal::Util
には、次のコンストラクターとメソッドが定義されています。
new
: そのクラスの新しいオブジェクトを作成します
_step1
_step2
doWork
: これはプレフィックス付きの_step1
andを呼び出します。_step2
Util::
doWork2
: これは接頭辞なしで_step1
呼び出します。_step2
Util::
doWork3
: これはプレフィックス付きの_step1
andを呼び出します。_step2
__PACKAGE__
doWork4
: これは、 から取得した接頭辞を付けて呼び出さ_step1
れ_step2
まし$class
たref
。
クラスはメソッドを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