Object Oriented Programming in Perl

Object Oriented Programming in Perl
Tatsuhiko Miyagawa
[email protected]
Edge, Co.,Ltd. / Shibuya Perl Mongers
LL Saturday 2003
アジェンダ

Perl OO Basic




Perl OO Advanced



名前空間と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”
クラス/オブジェクト

package と bless



クラスは名前空間(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
継承

@ISA 配列で表現(is-a)


base プラグマ使用を推奨
多重継承も可能
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
デストラクタ

DESTROYメソッド


オブジェクト消滅時に実行
リファレンスカウンタ
package Dog;
sub DESTROY {
my $self = shift;
print “$self->{name}: Bye!”;
}
use Dog;
my $dog1 = Dog->new(‘Scooby’);
{
my $dog2 = Dog->new(‘Scrappy’);
}
Scrappy:
! Bye!
Scooby:! Bye!
Copyright 2003 Shibuya Perl Mongers
LL Saturday 2003
AUTOLOAD

未定義メソッドをキャッチ


アクセサの自動生成
メソッドのキャッシング・遅延ロード
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
演算子オーバーロード

overload プラグマを使用


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, $dog;
\&name,
\&weight,
=> 1;
shift->{name} }
shift->{weight} }
Copyright 2003 Shibuya Perl Mongers
LL Saturday 2003
UNIVERSAL

すべてのオブジェクトの祖先クラス



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
可視性

public, private, protected




用意されてません
アトリビュートはアクセサメソッドで保護
private メソッドは _ を先頭に
paranoia な人は


caller() でチェック
Class::Fields, Attribute::Protected
Copyright 2003 Shibuya Perl Mongers
LL Saturday 2003
Perl OO Advanced
Design Patterns (1/3)

Singleton Pattern


スタティック変数はレキシカル変数を利用
パッケージ変数に格納 (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)

Decorator Pattern



AUTOLOAD を利用してメソッドを転送
Class::Decorator
Class::Delegate
package ReverseDecorator;
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)

Class::* Modules



Class::Composite
Class::Prototype
Object::PerlDesignPatterns

Perl でパターンやるなら必読
Copyright 2003 Shibuya Perl Mongers
LL Saturday 2003
Mix-in

多重継承はダイアモンド型の問題あり



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

Aspect Oriented Programming



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)

rubyisms.pm


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)

autobox.pm


use builtin datatypes as first-class objects
Perl 5.8.1 RC4 へのパッチ必要
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
Perl の OO は現場で使えるか?
事例紹介

Sledge (http://sl.edge.jp/)


MVC なWebアプリケーションフレームワー
ク
オブジェクト指向




アプリケーション: クラス
ページ: メソッド
Abstract Factory, Strategy, Singleton,
Template Method などのパターンを利用
Class::DBI (O/R Mapping) とコンボが強力
Copyright 2003 Shibuya Perl Mongers
LL Saturday 2003
Sledge の適用事例

エッジ社ではほぼ全てのプロジェクト
で利用



プロジェクトあたりプログラマ 2-4名
開発期間 2w-6w
2001年夏に開発 2002年始めから標準化

浸透には時間がかかった


Sledge 自体の安定性の問題もあり
チーフエンジニアへの教育

各プロジェクトで採用→OJTとノウハウ共有
(CVS, Wiki, Mailing List)
Copyright 2003 Shibuya Perl Mongers
LL Saturday 2003
まとめ


基本的OO機能は備わっている
何でも動的



$obj->$method();
push @{“$class\::ISA”}, $another;
Hackすれば大体のことは実現できる


何をしてるかわかる人がやる
何をしてるかわからないようにする
Copyright 2003 Shibuya Perl Mongers
LL Saturday 2003