2016/03/14 07:30:41

Perl の関数をオーバーライドする

Perl で関数を上書くいくつかの方法

一時的なオーバーライド

(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
サイト内検索