要するに、JavaScriptにおけるOOPみたいなものだと思ってもらえれば良いみたいです。
で、Perlでもそういうことを簡単にやってのけるような実装が無いわけじゃないみたいですが(インスタンスベースOOPで必要な機能を部分的にカバーするモジュールなら幾つかある)、あくまで「インスタンスベースOOPの面倒をみてやるぜー」的なモジュールとなると、そういうのは見つけられなかったです。
また、Perlの言語レベルである程度カバーできる箇所もあるんですけど、それってキモチワルい見た目のソースを書くことにつながったりするので、そういうのはナシって方向で考えると、
「あれ、PerlでインスタンスベースOOP実現するのって、なんかすっきりしたやり方が無い様な。。。」
という結果に行き着いてしまいました。。。
そんなわけで、インスタンスベースOOPの面倒を見るモジュールとしてPlassというのを作ってみました!
こんな感じで使えます
ちなみに以下のソースは、Cyanというインスタンスベースな言語のドキュメントの一部にあったサンプルソースです。Human = Object.child() Human.walk = ^(self, dir){ say(self.name + " walked " + dir + ".") } Superman = Human.child() Superman.fly = ^(self, dir){ say(self.name + " flew " + dir + ".") } human = Human.child() human.name = "John" human.walk("east") #=> John walked east. superman = Superman.child() superman.name = "Clark" superman.fly("north") #=> Clark flew north. superman.walk("west") #=> Clark walked west.
これをPerlでPlassを使って書き換えると、以下の様になります。
use warnings; use strict; use Plass; # plassコマンドでPlassオブジェクトのクローンを作成 my $Human = plass; # Humanインスタンスにwalkメソッドを追加 $Human->method( walk => sub { my ( $self, $dir ) = @_; print $self->name. " walked ". $dir. ".\n"; } ); # SupermanインスタンスはHumanインスタンスのクローン my $Superman = $Human->plass; # Supermanインスタンスにflyメソッドを追加 $Superman->method( fly => sub { my ( $self, $dir ) = @_; print $self->name. " flew ". $dir. ".\n"; } ); # humanインスタンスはHumanインスタンスのクローン my $human = $Human->plass; # humanインスタンスのname値を設定 $human->name( "John" ); # Humanインスタンスから継承したwalkメソッドを実行 $human->walk( "east" ); # supermanインスタンスはSupermanインスタンスのクローン my $superman = $Superman->plass; # supermanインスタンスのname値を設定 $superman->name( "Clark" ); # Supermanインスタンスから継承したflyメソッドとwalkメソッドを実行 $superman->fly( "north" ); $superman->walk( "west" );
出力結果は
John walked east. Clark flew north. Clark walked west.となり、Cyanのそれと同じ出力(Cyanのドキュメントによると、ですが^^;)になっていることがわかります。
Plassではインスタンス継承時にメンバ変数やメソッドを一気に被せることもできますので、上のコードは以下のように書くことが可能です。
use warnings; use strict; use Plass; # Humanインスタンスの定義 my $Human = plass( walk => sub { my ( $self, $dir ) = @_; print $self->name. " walked ". $dir. ".\n"; } ); # Supermanインスタンスの定義 my $Superman = $Human->plass( fly => sub { my ( $self, $dir ) = @_; print $self->name. " flew ". $dir. ".\n"; } ); # humanインスタンスの定義 my $human = $Human->plass( name => "John" ); # humanインスタンスのwalkメソッドを実行 $human->walk( "east" ); # supermanインスタンスの定義 my $superman = $Superman->plass( name => "Clark" ); # supermanインスタンスのflyメソッドおよびwalkメソッドを実行 $superman->fly( "north" ); $superman->walk( "west" );
出力結果は
John walked east. Clark flew north. Clark walked west.先ほどと同様ですね。
もし興味を持っていただけたら
ytnobody/Plass - GitHub
にアップしてありますので、お気軽にダウンロードしていただければ幸いです!
但し現在のところ、圧倒的にテストが不足してますので、そこんとこは予めご了承ください。
ちなみに僕はインスタンスベースOOP言語は今までJavaScriptしか触ったことが無いです(と思います)。
もし「真のインスタンスベースとはここが違うじゃねえか!」などというツッコミとか「こうした方が使いやすいんじゃないか」などのご提案、「これをこう使うと変になる!」みたいなバグ報告などなどございましたら、@ytnobodyまでご連絡ください!
余談ですが
Cyan言語の開発者はなんと、高校生の頃にCyanを開発したそうですよ!猛者ですね!Cyan言語についても興味がでてきました!
0 件のコメント:
コメントを投稿