PERLBOT(1)               USER COMMANDS                 PERLBOT(1)



NAME
     perlbot - Bag'o Object Tricks For Perl5 (the BOT)

INTRODUCTION
     これから示す技とヒントは、インスタンス変数の利用やオブジェク
     トとクラスの関係といったことについての、好奇心をそそることを
     目指しています。 これを読む方は、オブジェクト指向の定義と方
     法論に関する適切な本も、読んだ方がよいでしょう。 このドキュ
     メントは、Perl 5 のオブジェクト指向機能の総括的なガイドを目指
     すものでもなければ、スタイルガイドとして作られているわけでも
     ありません。

     Perl のモットーは、ここでも生きています: 「やり方は 1 通りで
     はない。」

インスタンス変数
     無名の配列や無名のハッシュには、インスタンス変数を入れておく
     ことができます。 名前付きパラメータの例もいっしょに示してお
     きます。

             package Foo;

             sub new {
                     my $type = shift;
                     my %params = @_;
                     my $self = {};
                     $self->{'High'} = $params{'High'};
                     $self->{'Low'}  = $params{'Low'};
                     bless $self;
             }

             package Bar;

             sub new {
                     my $type = shift;
                     my %params = @_;
                     my $self = [];
                     $self->[0] = $params{'Left'};
                     $self->[1] = $params{'Right'};
                     bless $self;
             }

             package main;

             $a = new Foo ( 'High' => 42, 'Low' => 11 );
             print "High=$a->{'High'}\n";
             print "Low=$a->{'Low'}\n";

             $b = new Bar ( 'Left' => 78, 'Right' => 40 );
             print "Left=$b->[0]\n";
             print "Right=$b->[1]\n";




Perl manpages Last change: Release 5.0 Patchlevel 00            1






PERLBOT(1)               USER COMMANDS                 PERLBOT(1)



スカラインスタンス変数
     無名のスカラは、1 つのインスタンス変数が必要とされるときにだ
     け、使うことができます。

             package Foo;

             sub new {
                     my $type = shift;
                     my $self;
                     $self = shift;
                     bless \$self;
             }

             package main;

             $a = new Foo 42;
             print "a=$$a\n";


インスタンス変数継承
     この例では、新しいクラスで、取り込むためのスーパークラスから、
     インスタンスを継承する方法を示します。 この継承を行なうには、
     コンストラクタ内で新しいオブジェクトに対して、スーパークラスの
     コンストラクタを呼び出して継承部分の初期化を行なった後、自分自
     身のインスタンス変数の追加を行ないます。

             package Bar;

             sub new {
                     my $self = {};
                     $self->{'buz'} = 42;
                     bless $self;
             }

             package Foo;
             @ISA = qw( Bar );

             sub new {
                     my $self = new Bar;
                     $self->{'biz'} = 11;
                     bless $self;
             }

             package main;

             $a = new Foo;
             print "buz = ", $a->{'buz'}, "\n";
             print "biz = ", $a->{'biz'}, "\n";







Perl manpages Last change: Release 5.0 Patchlevel 00            2






PERLBOT(1)               USER COMMANDS                 PERLBOT(1)



オブジェクトの関係
     以下の例では、オブジェクト間の「包含」および「使用」といわれ
     る関係をインプリメントする方法を示します。

             package Bar;

             sub new {
                     my $self = {};
                     $self->{'buz'} = 42;
                     bless $self;
             }

             package Foo;

             sub new {
                     my $self = {};
                     $self->{'Bar'} = new Bar ();
                     $self->{'biz'} = 11;
                     bless $self;
             }

             package main;

             $a = new Foo;
             print "buz = ", $a->{'Bar'}->{'buz'}, "\n";
             print "biz = ", $a->{'biz'}, "\n";





























Perl manpages Last change: Release 5.0 Patchlevel 00            3






PERLBOT(1)               USER COMMANDS                 PERLBOT(1)



スーパークラスのメソッドのオーバライド
     以下の例は、スーパークラスのメソッドをオーバライドし、オーバ
     ライドされた後でそのメソッドを呼び出す方法を示します。
     Foo::Inherit クラスを使って、オーバライドされたスーパークラ
     スのメソッドが、実際には、どこで定義されているか知らなくても、
     そのメソッドを呼び出せるようにしています。

             package Buz;
             sub goo { print "here's the goo\n" }

             package Bar; @ISA = qw( Buz );
             sub google { print "google here\n" }

             package Baz;
             sub mumble { print "mumbling\n" }

             package Foo;
             @ISA = qw( Bar Baz );
             @Foo::Inherit::ISA = @ISA;  # オーバライドされたメソ
                                         # ッドのアクセス

             sub new { bless [] }
             sub grr { print "grumble\n" }
             sub goo {
                     my $self = shift;
                     $self->Foo::Inherit::goo();
             }
             sub mumble {
                     my $self = shift;
                     $self->Foo::Inherit::mumble();
             }
             sub google {
                     my $self = shift;
                     $self->Foo::Inherit::google();
             }

             package main;

             $foo = new Foo;
             $foo->mumble;
             $foo->grr;
             $foo->goo;
             $foo->google;












Perl manpages Last change: Release 5.0 Patchlevel 00            4






PERLBOT(1)               USER COMMANDS                 PERLBOT(1)



SDBM を伴う関係の使用
     この例は、SDBM クラスのためのインタフェースを示します。 こ
     れは、SDBM クラスと新しいクラス Mydbm との間の「使用」関係を
     作ります。

             use SDBM_File;
             use POSIX;

             package Mydbm;

             sub TIEHASH {
                 my $self = shift;
                 my $ref  = SDBM_File->new(@_);
                 bless {'dbm' => $ref};
             }
             sub FETCH {
                 my $self = shift;
                 my $ref  = $self->{'dbm'};
                 $ref->FETCH(@_);
             }
             sub STORE {
                 my $self = shift;
                 if (defined $_[0]){
                     my $ref = $self->{'dbm'};
                     $ref->STORE(@_);
                 } else {
                     die "Cannot STORE an undefined key in Mydbm\n";
                 }
             }

             package main;

             tie %foo, Mydbm, "Sdbm", O_RDWR|O_CREAT, 0640;
             $foo{'bar'} = 123;
             print "foo-bar = $foo{'bar'}\n";

             tie %bar, Mydbm, "Sdbm2", O_RDWR|O_CREAT, 0640;
             $bar{'Cathy'} = 456;
             print "bar-Cathy = $bar{'Cathy'}\n";


コード再利用の考慮
     オブジェクト指向言語の 1 つの強みは、古いコードが新しいコー
     ドを使うことが簡単にできるということです。 次の例では、まず
     どのようなことがコードの再利用を妨げるかを示して、それから、
     どのように再利用を推し進めるかを示します。

     最初の例は、「プライベートな」メソッド BAZ() をアクセスする
     ために、メソッドを呼び出すのにパッケージ名をすべて付けている
     クラスを示します。 次の例で、この BAZ() をオーバライドする
     ことができないことを示します。




Perl manpages Last change: Release 5.0 Patchlevel 00            5






PERLBOT(1)               USER COMMANDS                 PERLBOT(1)



             package FOO;

             sub new { bless {} }
             sub bar {
                     my $self = shift;
                     $self->FOO::private::BAZ;
             }

             package FOO::private;

             sub BAZ {
                     print "in BAZ\n";
             }

             package main;

             $a = FOO->new;
             $a->bar;

     さて、BAZ() をオーバライドしてみましょう。 FOO::bar()が
     GOOP::BAZ() を呼ぶようにしたいのですが、FOO::bar() では、明
     示的に FOO::private::BAZ() を呼んでいるため、これができませ
     ん。

             package FOO;

             sub new { bless {} }
             sub bar {
                     my $self = shift;
                     $self->FOO::private::BAZ;
             }

             package FOO::private;

             sub BAZ {
                     print "in BAZ\n";
             }

             package GOOP;
             @ISA = qw( FOO );
             sub new { bless {} }

             sub BAZ {
                     print "in GOOP::BAZ\n";
             }

             package main;

             $a = GOOP->new;
             $a->bar;





Perl manpages Last change: Release 5.0 Patchlevel 00            6






PERLBOT(1)               USER COMMANDS                 PERLBOT(1)



     再利用可能なコードを作るためには、クラス FOO::private の階層
     をなくして、クラス FOO を修正しなければなりません。 次の例
     で、メソッド FOO::BAZ() の代わりに GOOP::BAZ() を呼べるよう
     にする再利用可能なクラス FOO を示します。

             package FOO;

             sub new { bless {} }
             sub bar {
                     my $self = shift;
                     $self->BAZ;
             }

             sub BAZ {
                     print "in BAZ\n";
             }

             package GOOP;
             @ISA = qw( FOO );

             sub new { bless {} }
             sub BAZ {
                     print "in GOOP::BAZ\n";
             }

             package main;

             $a = GOOP->new;
             $a->bar;


クラスコンテキストとオブジェクト
     パッケージとクラスのコンテキストの問題を解決するために、オブ
     ジェクトを使います。 メソッドが必要とするものはすべて、オブ
     ジェクトを通じて利用するか、メソッドへの引数として渡すように
     しなければなりません。

     クラスには、メソッドが使用する静的なデータやグローバルなデー
     タを用意することがあります。 サブクラスで、このデータを新し
     いデータでオーバライドしたいこともあるでしょう。 このような
     ときに、サブクラスでは新しいデータを探す方法を知ることができ
     ません。

     この問題は、メソッドのコンテキストを定義するために、オブジェ
     クトを使うことで解決することができます。 データへのリファレ
     ンスを探すために、メソッドにオブジェクトを覗かせます。 別解
     として、メソッドに追いかけさせ (「これは、私のクラスのものか、
     それともサブクラスのものなのか。 いったい、どのサブクラスの
     ものか。」)るものですが、不便で、遺物のようなものにしかなら
     ないでしょう。 メソッドに対して、オブジェクトにデータがどこ
     にあるのかを言わせればよいでしょう。




Perl manpages Last change: Release 5.0 Patchlevel 00            7






PERLBOT(1)               USER COMMANDS                 PERLBOT(1)



             package Bar;

             %fizzle = ( 'Password' => 'XYZZY' );

             sub new {
                     my $self = {};
                     $self->{'fizzle'} = \%fizzle;
                     bless $self;
             }

             sub enter {
                     my $self = shift;

                     # %Bar::fizzle を使うべきか、%Foo::fizzle を
                     # 使うべきかを考えてはいけません。 オブジェ
                     # クトの方でもう分かっていますから、単に尋く
                     # だけです。
                     #
                     my $fizzle = $self->{'fizzle'};

                     print "The word is ", $fizzle->{'Password'}, "\n";
             }

             package Foo;
             @ISA = qw( Bar );

             %fizzle = ( 'Password' => 'Rumple' );

             sub new {
                     my $self = Bar->new;
                     $self->{'fizzle'} = \%fizzle;
                     bless $self;
             }

             package main;

             $a = Bar->new;
             $b = Foo->new;
             $a->enter;
             $b->enter;















Perl manpages Last change: Release 5.0 Patchlevel 00            8