Perl の関数をオーバーライドする ======================== Perl で関数を上書くいくつかの方法 -------------------------- {{TOC 3-}} ### 一時的なオーバーライド (Foo.pm) package Foo; use strict; use warnings; sub bar { my $baz = shift; $baz * 2; } 1; (hoge.pl) #!/usr/bin/perl use strict; use warnings; use Perl6::Say; use Foo; say Foo::bar(3); # 6 { no warnings 'redefine'; local *Foo::bar = sub { my $baz = shift; $baz ** 2; }; say Foo::bar(3); # 9 } say Foo::bar(3); # 6 関数を、local で一時的に上書きする。 `no warnings 'redefine';` は関数の再定義を許してね、という宣言。 no warnings 'redefine'; local *Foo::bar = sub { my $baz = shift; $baz ** 2; }; ### グローバルにオーバーライドする (hoge.pl) #!/usr/bin/perl use strict; use warnings; use Perl6::Say; use Foo; say Foo::bar(3); # 6 { no warnings 'redefine'; *Foo::bar = sub { my $baz = shift; $baz ** 2; }; say Foo::bar(3); # 9 } say Foo::bar(3); # 9 local をつけなければ、グローバルに上書きされる。 ### プロトタイプ オーバーライドする関数に、プロトタイプが宣言されている場合は、上書く関数にもプロトタイプをつけないと、「Prototype mismatch: sub Foo::bar ($) vs none」などと警告が出る。 (Foo.pm) package Foo; use strict; use warnings; sub bar ($) { my $baz = shift; $baz * 2; } 1; (hoge.pl) #!/usr/bin/perl use strict; use warnings; use Perl6::Say; use Foo; say Foo::bar(3); # 6 { no warnings 'redefine'; *Foo::bar = sub ($) { my $baz = shift; $baz ** 2; }; say Foo::bar(3); # 9 } say Foo::bar(3); # 9 一時的な書き換えなら、警告はでない。 ### 組み込み関数のオーバーライド 組み込み関数を上書く場合は、BEGIN ブロックで、以下のようにする。 #!/usr/bin/perl use strict; use warnings; use Perl6::Say; BEGIN{ *CORE::GLOBAL::length = sub{ 'constant'; }; } say length('foo'); say CORE::length('foo'); # 書き換えられる前の関数 結果はこのようになります。 constant 3