動画で知るClass::C3とNEXTの違い
CatalystとかDBICを理解しようとすると頻繁に出てくるClass::C3。継承ツリーをどうにかするものらしいけど、挙動を把握するのは難しそうだなーという印象でした。
「CatalystもそのうちNEXTからClass::C3ベースに変わるし」なんて話題が出ても、そもそもどっちも分かってないのでちんぷんかんぷんです。
したら、牧さんが去年のYAPCでClass::C3について語ってるじゃありませんか。これすげー、めちゃめちゃ分かりやすい。
PHPは多重継承サポートしてないし、それ以前にPerl使ってたころはそもそもOOP自体ちゃんと理解できてなかったので、多重継承なんて考えたのは初めて。そんな自分の印象としては、むしろNEXTの挙動の方が不自然なように思えます。
具体的にはこんな感じで使えばいいのかな。
#!/usr/bin/perl use strict; use warnings; package MyApp::Filter; use Class::C3; INIT { Class::C3::initialize() } sub filter { my ( $self, $arg ) = @_; return "[$arg]"; } package MyApp::Filter::Reverse; use base qw(MyApp::Filter); sub filter { my ( $self, $arg ) = @_; $self->next::method( scalar reverse $arg ); } package MyApp::Filter::Ucfirst; use base qw(MyApp::Filter); sub filter { my ( $self, $arg ) = @_; $self->next::method( ucfirst $arg ); } package MyApp; use base qw( MyApp::Filter::Ucfirst MyApp::Filter::Reverse ); sub new { my $class = shift; bless {}, $class; } sub process { my ( $self, $arg ) = @_; return $self->filter( $arg ); } package main; use Perl6::Say; my $obj = MyApp->new; say $obj->process( 'hoge' );
ucfirstしてreverseして、最後にブラケットでくくって、出力は [egoH] になる。
MyAppの継承を
use base qw( MyApp::Filter::Reverse MyApp::Filter::Ucfirst );
にすると、reverseしてからucfirstして、最後にMyApp::Filterするのは変わらなくて [Egoh] になる。いいねこれ。