overloadプラグマの使い方

404 Blog Not Found:紹介 - Software Design 2013年06月号

呼ばれてないけど勝手に添削。

use overload
  '""' => 'toString',
  '_'  => 'add',
;

はないわー。そこは

use overload
  '""' => \&toString,
  '_'  => \&add,
;

でしょうが。

いいえ、overloadプラグマの引数は文字列でいいんです。でないとサブクラスでオーバーライドできませんから。

つまり、overloadプラグマへ与えるメソッドの実体$methodは、$obj->$method()として与えられたかのように振舞うのです。コードリファレンスを与えると、メソッドのレシーバが何であろうとそのコードリファレンスが呼び出されてしまいます。文字列であれば、サブクラスでたとえばtoString()メソッドをオーバーライドしたときに正しくそのサブクラスのtoString()メソッドが呼び出されます。オーバーライドしたメソッドを適切に呼び出すということであれば'""' => sub { shift()->toString() }でもかまいませんが、ぼくは文字列で指定するほうが簡潔なので好きです。

以下検証コード:

#!perl
use 5.14.0;
use strict;
use warnings;

package ByStr {
    use overload '""' => 'toString';

    sub new {
        my($class) = @_;
        return bless {}, $class;
    }
    sub toString { __PACKAGE__ }
}

package ByCodeRef {
    use overload '""' => \&toString;

    sub new {
        my($class) = @_;
        return bless {}, $class;
    }
    sub toString { __PACKAGE__ }
}

package DerivedFromByStr {
    use parent -norequire, 'ByStr';

    sub toString { __PACKAGE__ }
}

package DerivedFromByCodeRef {
    use parent -norequire, 'ByCodeRef';

    sub toString { __PACKAGE__ }
}

say DerivedFromByStr->new();     # "DerivedFromByStr" <- オーバーライドできている
say DerivedFromByCodeRef->new(); # "ByCodeRef" <- オーバーライドできていない