Class::OOorNoでゴネゴネ

Class::OOorNOなるものを発見したので、ちょっとやってみました。

Class::OOorNOはその名の通りオブジェクト指向か否かを吸収してくれるモジュールです。
オブジェクト呼出しでもクラス呼出しでもサブルーチン呼出しでも動くようにしたい!という時に重宝するのでは無かろうかと。(File::statチックなモジュール作る時とか。)

さわりをざっくり

#!/usr/bin/perl
use strict;
package Foo;
use Class::OOorNO qw(OOorNO myargs);
use YAML;
use base qw(Class::Accessor);

sub dump_myargs {
    my (@args) = myargs(@_);
    warn YAML::Dump @args;
}
 
sub show_call_style {
    my $class = __PACKAGE__;
    if (ref OOorNO(@_)) {
        warn $class. "::object method";
    } elsif (OOorNO(@_)) {
        warn $class. "::class method"
    } else {
        warn $class. "::subroutine";
    }
}

package main;

my $args = { foo => 'A', bar => 'B'};

sub obj_style {
    my $foo = Foo->new;
    $foo->show_call_style;
    $foo->dump_myargs($args);
}

sub class_style {
    Foo->show_call_style;
    Foo->dump_myargs($args);
}

sub subroutine_style {
    Foo::show_call_style;
    Foo::dump_myargs($args);
}
 
&obj_style;
&class_style;
&subroutine_style;

結果

Foo::object method at ./foo.pl line 20.
---
bar: B
foo: A
Foo::class method at ./foo.pl line 22.
---
bar: B
foo: A
Foo::subroutine at ./foo.pl line 24.
---
bar: B
foo: A

myargs
何が一番困るってFoo::barとFoo->barで引数の数が変わってくるとこです。
そこで

my (@args) = @_;

の変わりに

my (@args) = myargs(@_);

としてあげると第1引数($selfとか$classとか)の状態から判断し必要な(実際に渡された)引数を返してくれます。

OOorNO
状態を判断するメソッドです。上記のshow_call_styleのようにどう呼ばれたが判別できます。


やってみました。

古いモジュールをOOに!
従来動いてるモジュールがあって従来の機能を生かしつつ、それをOOにしたい。的な感じで。
サンプルはファイルの最終更新時をYYYY-MM-DDで返してくれるだけのモジュールです。
そこにオブジェクトメソッドを足してみました。

#!/usr/bin/perl
 
use strict;
 
package File::MDate;
 
use Class::OOorNO qw(OOorNO myargs);
use DateTime;
 
use base qw(Class::Accessor);
 
sub file_mdate {
    # my ($file) = @_;
    my ($file) = myargs(@_);
    DateTime->from_epoch(epoch => (stat $file)[9])->ymd;
}
 
sub _is_subroutine_style {
    return ref OOorNO(@_) || OOorNO(@_) ? 0 : 1;
}
 
sub obj_method {
    if (_is_subroutine_style(@_)) {
        my $meth = (caller(0))[3];
        die sprintf "%s is object method.", $meth;
    }
    # オブジェクトを使った処理...
}

package main;
 
my $file = './text.txt';
 
# Object method
my $mdate = File::MDate->new;
warn $mdate->file_mdate($file);
 
$mdate->obj_method;
File::MDate::obj_method;
warn File::MDate->file_mdate($file);

結果

2007-02-28 at ./bar.pl line 37.
File::MDate::obj_method is object method. at ./bar.pl line 26.

とりあえず、myargsで何呼び出しでも引数を正しく受けれるようにします。
そして、新たに追加したobject用メソッド(サンプルだとクラス呼出しでもokになってまするが。。)に
サブルーチン呼び出しした場合dieするように仕込んでおきます。