parent.pm読んでみた

深夜にバカやってないで会社でバカやりましょう、いつも通り。
自分がクビにならないのが常々不思議である。

parent.pm

中にはメソッドはimportが1個のみ、行数も少ない。これなら軽く読める。

package parent;
use strict;
use vars qw($VERSION);
$VERSION = '0.221';

sub import {
    my $class = shift;

    my $inheritor = caller(0);

    if ( @_ and $_[0] eq '-norequire' ) {
        shift @_;
    } else {
        for ( my @filename = @_ ) {
            if ( $_ eq $inheritor ) {
                warn "Class '$inheritor' tried to inherit from itself\n";
            };

            s{::|'}{/}g;
            require "$_.pm"; # dies if the file is not found
        }
    }

    {
        no strict 'refs';
        # This is more efficient than push for the new MRO
        # at least until the new MRO is fixed
        @{"$inheritor\::ISA"} = (@{"$inheritor\::ISA"} , @_);
    };
};

解説

まあ、今更な上に簡単だけど、日記なので。

バージョン宣言

use vars qw($VERSION);

何故ourを使わないのかは不明。

sub import

sub import {
    my $class = shift;

    my $inheritor = caller(0);

use Moduleは以下に等しいので、

BEGIN { require Module; import Module LIST; }

$classはparentである。

$inheritorはuse parent〜って打ったパッケージ名。

    if ( @_ and $_[0] eq '-norequire' ) {
        shift @_;
    }

use parent qw/-norequire CGI/; とかだったらここにくるようだ。こんなオプション初めて知った。
こう書いたらrequireせずに継承だけすんのね。

 else {
        for ( my @filename = @_ ) {
            if ( $_ eq $inheritor ) {
                warn "Class '$inheritor' tried to inherit from itself\n";
            };

            s{::|'}{/}g;
            require "$_.pm"; # dies if the file is not found
        }


use parent qw/Hoge Huga Foo/; とかやったら、Hoge Huga Fooが@_になる。
自分自身を継承しようとしたらwarnする。warnするだけで継承するけど。

や'を/に置換。requireするときはHoge::HugaじゃなくてHoge/Hugaと書くので。

そういえば、以前は::じゃなくて'もパスのセパレータに使えたんだった。今はどうなんだろう。わざわざ古い見づらい書き方試す必要もないのでスルー。
require失敗したら、存在しないモジュールを継承しようとしてるので死亡。

    {
        no strict 'refs';
        # This is more efficient than push for the new MRO
        # at least until the new MRO is fixed
        @{"$inheritor\::ISA"} = (@{"$inheritor\::ISA"} , @_);
    };
};


ソフトリファレンス使って、use parentって書いてあるパッケージの@ISAに対象全部突っ込んで終わり。

このやり方は、少なくとも新たなMROが作られるまでは、新たなMROにpushするより効率的だよ!

だそうな。


普段使ってるモジュールのソース読むのって大事ですねと。面白いし。
問題はこんな時間まで起きてるから今日も会社で眠いってことだ。

追記

>fbisさん
なるほど、ありがとうございます。ただ、parentって割と新しいのに、古いバージョンのperlで使うのかなって思うのですが、そこは使う側の都合ですね。