Object Oriented Programming in Perl Tatsuhiko Miyagawa miyagawabulknews
Object Oriented Programming in Perl Tatsuhiko Miyagawa miyagawa@bulknews. net Edge, Co. , Ltd. / Shibuya Perl Mongers LL Saturday 2003
アジェンダ n Perl OO Basic l l l n Perl OO Advanced l l n 名前空間とbless 継承/デストラクタ AUTOLOAD/overload Design Patterns Mix-in, AOP 事例紹介 Copyright 2003 Shibuya Perl Mongers LL Saturday 2003
Perl OO Basic Object-oriented Perl is a small amount of additional syntax and semantics, added to the existing imperative features of the language. Damian Conway in “Object Oriented Perl”
クラス/オブジェクト n package と bless l l l クラスは名前空間(package)で定義 メソッドはクラス内のサブルーチン bless でリファレンスの実体をオブジェクトに package Dog; use Dog; sub new { my($class, $name) = @_; bless { name => $name }, $class; } my $dog = Dog->new(‘Snoopy’); $dog->bark(); sub bark { my $self = shift; print “bark: $self->{name}”; } Copyright 2003 Shibuya Perl Mongers LL Saturday 2003
継承 n @ISA 配列で表現(is-a) l base プラグマ使用を推奨 l 多重継承も可能 package Animal; sub run { my $self = shift; print “running!”; } use Dog; my $dog = Dog->new(‘Snoopy’); $dog->bark(); # Dog: : bark $dog->run(); # Animal: : run package Dog; # @Dog: : ISA = qw(Animal); use base qw(Animal); sub bark { } Copyright 2003 Shibuya Perl Mongers LL Saturday 2003
デストラクタ n DESTROYメソッド l l オブジェクト消滅時に実行 リファレンスカウンタ package Dog; sub DESTROY { my $self = shift; print “$self->{name}: Bye!”; } use Dog; my $dog 1 = Dog->new(‘Scooby’); { my $dog 2 = Dog->new(‘Scrappy’); } Scrappy: ! Bye! Scooby: ! Bye! Copyright 2003 Shibuya Perl Mongers LL Saturday 2003
AUTOLOAD n 未定義メソッドをキャッチ l l アクセサの自動生成 メソッドのキャッシング・遅延ロード package Dog; use vars qw($AUTOLOAD); my $accessors = { name => 1 }; sub AUTOLOAD { my $self = shift; (my $method = $AUTOLOAD) =~ s/. *: //; return $self->{$method} if $accessors->{$method}; die “Unknown method: $method” } Copyright 2003 Shibuya Perl Mongers my $dog = Dog->new(‘Snoopy’); my $name = $dog->name(); LL Saturday 2003
演算子オーバーロード n overload プラグマを使用 l l 5. 6以降は演算子が増えた fallback オプション package Dog; sub new { my($class, $name, $weight) = @_; # … } use overload q(“”) => q(0+) => fallback sub name { sub weight { my $dog = Dog->new(“Snoopy”, 13. 5); printf “name is %s, weight is %f”, $dog; &name, &weight, => 1; shift->{name} } shift->{weight} } Copyright 2003 Shibuya Perl Mongers LL Saturday 2003
UNIVERSAL n すべてのオブジェクトの祖先クラス l l l can(), isa() を定義 can() はメソッドのリファレンスを返す AUTOLOAD と併用すると … my $dog = Dog->new(); $dog->isa(‘Dog’); # true $dog->isa(‘Animal’); # true $dog->isa(‘Man’); # false my $bark = $dog->can(‘bark’); $man->$bark(); Copyright 2003 Shibuya Perl Mongers package UNIVERSAL; sub AUTOLOAD { my $self = shift; } すべてのクラスの未定義メソッドはここに! LL Saturday 2003
可視性 n public, private, protected l l l n 用意されてません アトリビュートはアクセサメソッドで保護 private メソッドは _ を先頭に paranoia な人は l l caller() でチェック Class: : Fields, Attribute: : Protected Copyright 2003 Shibuya Perl Mongers LL Saturday 2003
Perl OO Advanced
Design Patterns (1/3) n Singleton Pattern l l スタティック変数はレキシカル変数を利用 パッケージ変数に格納 (Class: : Singleton) package Printer; my $instance = Printer->new(); sub instance { $instance } package Printer; use base qw(Class: : Singleton); sub _new_instance { … } オブジェクトが1つしかないことは保証できない Copyright 2003 Shibuya Perl Mongers LL Saturday 2003
Design Patterns (2/3) n Decorator Pattern l l l AUTOLOAD を利用してメソッドを転送 Class: : Decorator Class: : Delegate package Reverse. Decorator; sub new { my($class, $obj) = @_; bless { o => $obj }, $class; } sub AUTOLOAD { my($self, @args) = @_; (my $meth = $AUTOLOAD) =~ s/. *: //; my @new_args = map reverse($_), @args; $self->{o}->$meth(@new_args); } Copyright 2003 Shibuya Perl Mongers LL Saturday 2003
Design Patterns (3/3) n Class: : * Modules l l n Class: : Composite Class: : Prototype Object: : Perl. Design. Patterns l Perl でパターンやるなら必読 Copyright 2003 Shibuya Perl Mongers LL Saturday 2003
Mix-in n 多重継承はダイアモンド型の問題あり l l l Exporter を利用して mix-in を実装 Ruby の Module に相当 mixin. pm (M. Schwern) package Speakable; use base qw(Exporter); @EXPORT = qw(speak); sub speak { my $self = shift; print “my name: “, $self->name; } package Man; use Speakable; sub speak { my $self = shift; print “my name: “, $self->name; } 実装を借りてくるようなイメージ Copyright 2003 Shibuya Perl Mongers LL Saturday 2003
AOP n Aspect Oriented Programming l l l PerlのOOは動的束縛 他クラスのメソッドを上書き Aspect. pm my $orig = Man->can(‘walk’); *Man: : walk = sub { warn “Man: : walk here”; goto &$orig; }; Copyright 2003 Shibuya Perl Mongers LL Saturday 2003
おまけ(1/2) n rubyisms. pm l l Simon Cozens 作 Steal some features from Ruby package Foo; use rubyisms; sub initialize { self->{things} = [ @_ ]; self->another_method; } sub array_iterator (&@) { yield() for @_; } array_iterator { print $_[0], “n” } (“Hello”, “World”); sub my_method { if ($interesting) { … } else { super } } Copyright 2003 Shibuya Perl Mongers LL Saturday 2003
おまけ(2/2) n autobox. pm l l use builtin datatypes as first-class objects Perl 5. 8. 1 RC 4 へのパッチ必要 use autobox; my $range = 10 ->to(1); my $ton = $range->[0]->mul(10); my $error = 3. 14 ->minus(22/7); my $greeting = "Hello, World"->upper(); $greeting->to_lower(); $greeting->for_each(&char_handler); my $arr = [ @_ ]->map(. . . )->sort(. . . ); Copyright 2003 Shibuya Perl Mongers LL Saturday 2003
事例紹介 n Sledge (http: //sl. edge. jp/) l MVC なWebアプリケーションフレームワーク l オブジェクト指向 アプリケーション: クラス p ページ: メソッド p l l Abstract Factory, Strategy, Singleton, Template Method などのパターンを利用 Class: : DBI (O/R Mapping) とコンボが強力 Copyright 2003 Shibuya Perl Mongers LL Saturday 2003
- Slides: 22