=encoding euc-jp =head1 名前 perltoot - トムによるPerlオブジェクト指向チュートリアル =head1 概要 Object-oriented programming is a big seller these days. Some managers would rather have objects than sliced bread. Why is that? What's so special about an object? Just what I an object anyway? オブジェクト指向プログラミングは、昨今の、ビッグセラーです。 マネージャーには、薄切りパン(訳註:良い発明のこと)よりもむしろオブジェクトを持ちたがる人もいます。 どうしてでしょうか? オブジェクトの、何がそんなに特別なんでしょうか? そもそも、オブジェクトとは一体I<なんでしょう>か? An object is nothing but a way of tucking away complex behaviours into a neat little easy-to-use bundle. (This is what professors call abstraction). Smart people who have nothing to do but sit around for weeks on end figuring out really hard problems make these nifty objects that even regular people can use. (This is what professors call software reuse.) オブジェクトは、きちんとした小さな使いやすい包みに包んで、 複雑なふるまいを遠くへやってしまう方法以外のなにものでもありません(専門家は、このことを抽象化と呼びます)。 本当に難しい問題を片付けようと、何週間もぼーっと過ごしている、かしこい人たちは、 普通の人でも使える、これらの素敵なオブジェクトを作ります(専門家は、このことをソフトウェアの再利用と呼びます)。 Users (well, programmers) can play with this little bundle all they want, but they aren't to open it up and mess with the insides. Just like an expensive piece of hardware, the contract says that you void the warranty if you muck with the cover. So don't do that. オブジェクトを使う人(たぶん、プログラマ)は、自分が欲しい小さな包みをいじることができます。 ですが、その包みを開けようとはしないし、その中を散らかそうともしないでしょう。 ちょうど、ハードウェアの高価な部分のように、契約は次のようになっています。 カバーをいじくれば、保証は無効になります、と。ですから、そんなことをしてはいけません。 The heart of objects is the class, a protected little private namespace full of data and functions. A class is a set of related routines that addresses some problem area. You can think of it as a user-defined type. The Perl package mechanism, also used for more traditional modules, is used for class modules as well. Objects "live" in a class, meaning that they belong to some package. オブジェクトの核心は、クラスです。クラスは、守られた小さな私的な名前空間であり、 データと関数に満ちています。クラスは関連したルーチンのセットであり、 いくつかの問題領域を扱います。クラスをユーザ定義の型と考えることもできます。 Perl のパッケージの仕組は、より伝統的なモジュールと同じように、クラスモジュールにも使われます。 オブジェクトは、クラスの中に、 "住んで(生きて)"います。 このことは、オブジェクトがいくつかのパッケージに属していることを意味します。 More often than not, the class provides the user with little bundles. These bundles are objects. They know whose class they belong to, and how to behave. Users ask the class to do something, like "give me an object." Or they can ask one of these objects to do something. Asking a class to do something for you is calling a I. Asking an object to do something for you is calling an I. Asking either a class (usually) or an object (sometimes) to give you back an object is calling a I, which is just a kind of method. たいてい、クラスは、それを使う人にいくつかの小さな包みを提供します。 それらの包みがオブジェクトです。オブジェクトは、自分が属しているクラスを知っていて、 どのように振る舞うかも知っています。クラスを使う人は、クラスに、何かをするように、 たとえば、"オブジェクトをちょうだい"のように、頼むか、 オブジェクトの1つに何かをするように頼むことができます。 クラスに何かをするように頼むことは、I<クラスメソッド>を呼ぶことです。 オブジェクトに何かをするように頼むことは、I<オブジェクトメソッド>を呼ぶことです。 クラス(ふつう)または、オブジェクト(たまに)に、オブジェクトを返すように頼むことは、 I<コンストラクタ>を呼ぶことです。コンストラクタは、メソッドの一種です。 That's all well and good, but how is an object different from any other Perl data type? Just what is an object I; that is, what's its fundamental type? The answer to the first question is easy. An object nis different from any other data type in Perl in one and only one way: you may dereference it using not merely string or numeric subscripts as with simple arrays and hashes, but with named subroutine calls. In a word, with I. それはそれとして、オブジェクトはPerlの他のデータ型とどのように違うのでしょうか? I<実際には>、オブジェクトは...オブジェクトの基礎の型は何なのでしょうか? 最初の質問に答えるのは、簡単です。 オブジェクトは、一つの、たった一つのやり方において、Perlの他のデータ型とは違っています。 オブジェクトをデリファレンスするのに、単純な配列やハッシュのように、 単なる文字列や数字の添字ではなく、名前の付けられたサブルーチンの呼出しを使います。 一言でいえば、I<メソッド>でデリファレンスします。 The answer to the second question is that it's a reference, and not just any reference, mind you, but one whose referent has been I()ed into a particular class (read: package). What kind of reference? Well, the answer to that one is a bit less concrete. That's because in Perl the designer of the class can employ any sort of reference they'd like as the underlying intrinsic data type. It could be a scalar, an array, or a hash reference. It could even be a code reference. But because of its inherent flexibility, an object is usually a hash reference. 二番目の答えは、次のようになります。オブジェクトはリファレンスですが、ただのリファレンスではありません。 注意してください。特別なクラス(パッケージ)にI<祝福(bless)され>ているリファレントを持っているものです。 リファレンスの種類は? たぶん、その質問の答えは、あまり具体的にはなりません。 Perlでは、基礎となる固有のデータ型として、リファレンスならどんな種類のものでも、 クラス設計者の好きなように使うことが出来るからです。 リファレンスなら、スカラーでも、配列でも、ハッシュでもかまいません。 コードのリファレンスすらありえます。 ですが、持ち前の柔軟性により、普通、オブジェクトはハッシュリファレンスです。 =head1 クラスを作る Before you create a class, you need to decide what to name it. That's because the class (package) name governs the name of the file used to house it, just as with regular modules. Then, that class (package) should provide one or more ways to generate objects. Finally, it should provide mechanisms to allow users of its objects to indirectly manipulate these objects from a distance. クラスを作る前に、クラスに何という名前を付けるかを決めなければなりません。 クラス(パッケージ)の名前は、普通のモジュールと同じように、クラスを納めるファイル名を左右します。 それから、そのクラス(パッケージ)は、一つか、それ以上の方法で、オブジェクトを生成する方法を提供すべきです。 最後に、クラス(パッケージ)は、オブジェクトを使う人に、 離れたところから間接的にオブジェクトを操作することのできるメカニズムを提供すべきです。 For example, let's make a simple Person class module. It gets stored in nthe file Person.pm. If it were called a Happy::Person class, it would be stored in the file Happy/Person.pm, and its package would become Happy::Person instead of just Person. (On a personal computer not running Unix or Plan 9, but something like Mac OS or VMS, the directory separator may be different, but the principle is the same.) Do not assume any formal relationship between modules based on their directory names. This is merely a grouping convenience, and has no effect on inheritance, variable accessibility, or anything else. 例えば、単純な Personクラスモジュールを作ってみましょう。このクラスモジュールは、 Person.pm に保存されます。もし、このクラスモジュールが、Happy::Person クラスと呼ばれるなら、 このクラスは、Happy/Person.pm ファイルに保存されます。 そして、そのパッケージは、ただの、Person ではなく、Happy::Person になります。 (Unix か、Plan 9 ではなく、Mac OS やVMSのようなOSの動いているパーソナルコンピュータ上では、 ディレクトリのセパレータは違っているでしょうが、原則は同じです)。 ディレクトリ名のベースとなるモジュールとの間にどのような公式な関係も想定してはいけません。 これは、単に、グループ別けを便利にしているだけで、継承や変数のアクセシビリティなど、 その他諸々に、何の効果も与えません。 For this module we aren't going to use Exporter, because we're a well-behaved class module that doesn't export anything at all. In order to manufacture objects, a class needs to have a I. A constructor gives you back not just a regular data type, but a brand-new object in that class. This magic is taken care of by the bless() function, whose sole purpose is to enable its referent to be used as an object. Remember: being an object really means nothing more than that methods may now be called against it. このモジュールにExporterは使わないでおきましょう。私たちは行儀が良いし、 行儀が良いクラスモジュールはまったく何もexportしないからです(訳註:文法が?)。 オブジェクトを作るためには、クラスに、I<コンストラクタメソッド>が必要です。 コンストラクタは、普通のデータ型ではなく、おろしたてのクラスのオブジェクトを返します。 この魔法は、bless() 関数によって、扱われます。bless() の唯一の目的は、 リファレンスをオブジェクトとして使えるようにすることです。 銘記:オブジェクトであることは、実際には、メソッドが、そのオブジェクトを背景にして、 呼ばれるということ以上に何も意味しません。 While a constructor may be named anything you'd like, most Perl programmers seem to like to call theirs new(). However, new() is not a reserved word, and a class is under no obligation to supply such. Some programmers have also been known to use a function with the same name as the class as the constructor. コンストラクタは、好きなように名付けても構いませんが、 ほとんどのPerlプログラマは、コンストラクタを、new() と呼ぶのを好むようです。 ですが、new() は、予約語ではありませんし、クラスにはそういったものを供給する 義務もありません。コンストラクタとして、クラスと同じ名前の関数を使うプログラマにがいることも知られています。 =head2 オブジェクトの表現(Representation) By far the most common mechanism used in Perl to represent a Pascal record, a C struct, or a C++ class is an anonymous hash. That's because a hash has an arbitrary number of data fields, each conveniently accessed by an arbitrary name of your own devising. Pascalのレコードや、Cの構造体や、C++のクラスを表すために、 Perlで使われている、もっとも一般的なメカニズムは、無名ハッシュです。 ハッシュには任意の数のデータ領域があり、自分でつけた任意の名前で、 それぞれにアクセスしやすいからです。 If you were just doing a simple struct-like emulation, you would likely go about it something like this: 単純な構造体ライクなエミュレーションをするなら、 次のようにすることができます: $rec = { name => "Jason", age => 23, peers => [ "Norbert", "Rhys", "Phineas"], }; If you felt like it, you could add a bit of visual distinction by up-casing the hash keys: 違いをつけたいと感じたら、大文字のハッシュキーによって、 見た目に、ちょっとした違いを加えることができます: $rec = { NAME => "Jason", AGE => 23, PEERS => [ "Norbert", "Rhys", "Phineas"], }; And so you could get at C<< $rec->{NAME} >> to find "Jason", or C<< @{ $rec->{PEERS} } >> to get at "Norbert", "Rhys", and "Phineas". (Have you ever noticed how many 23-year-old programmers seem to be named "Jason" these days? :-) これで、C<< $rec->{NAME} >> で、"Jason"を見付けることができるようになり、 また、C<< @{ $rec->{PEERS} } >>で、"Norbert" と、"Rhys"と"Phineas"を得ることができます。 (昨今、どれくらい多くの、23才のプログラマが、Jasonと名付けられているか気にしたことがありますか?:-) This same model is often used for classes, although it is not considered the pinnacle of programming propriety for folks from outside the class to come waltzing into an object, brazenly accessing its data members directly. Generally speaking, an object should be considered an opaque cookie that you use I to access. Visually, methods look like you're dereffing a reference using a function name instead of brackets or braces. これと同じモデルは、複数のクラスでよく使われてます。とはいっても、 クラスの外から、皆がオブジェクトにワルツを踊らせて、そのデータメンバにずうずうしく直接にアクセスすることは、 プログラミングの礼儀正しさの頂点をよく考えたものではありません。 概して、オブジェクトは、I<オブジェクトメソッド>を使ってアクセスする、不可解なクッキーと考えるべきです。 見た目には、メソッドは、ブラケットや、ブレイスの代わりに、 関数名を使って、リファレンスをデリファレンスしているように見えます。 =head2 クラスのインターフェース Some languages provide a formal syntactic interface to a class's methods, but Perl does not. It relies on you to read the documentation of each class. If you try to call an undefined method on an object, Perl won't complain, but the program will trigger an exception while it's running. Likewise, if you call a method expecting a prime number as its argument with a non-prime one instead, you can't expect the compiler to catch this. (Well, you can expect it all you like, but it's not going to happen.) 言語には、クラスのメソッドのための正式な総合のインターフェースを提供しているものもありますが、 Perl は、そうではありません。使う人がそれぞれのクラスのドキュメントを読むのを当てにしています。 定義されていないメソッドをオブジェクトで呼んだら、Perlは、文句を言おうとはしませんが、 プログラムは、実行している間に、例外をおこすでしょう。 同じように、引数に素数を期待するメソッドに、素数でない数字を引数にして呼んだとしても、 コンパイラがそのことをとらえてくれることは期待できません。 (たぶん、あなたは、コンパイラにあなたの好むすべてを期待するでしょうが、そんなことは起こりません。) Let's suppose you have a well-educated user of your Person class, someone who has read the docs that explain the prescribed interface. Here's how they might use the Person class: Personクラスを使う人が、よく教育された、 所定のインターフェースを説明するドキュメントを読んでいる人だと想定しましょう。 Personクラスの使いかたがここにあります: use Person; $him = Person->new(); $him->name("Jason"); $him->age(23); $him->peers( "Norbert", "Rhys", "Phineas" ); push @All_Recs, $him; # 後のために、オブジェクトを配列にいれます。 printf "%s is %d years old.\n", $him->name, $him->age; print "His peers are: ", join(", ", $him->peers), "\n"; printf "Last rec's name is %s\n", $All_Recs[-1]->name; As you can see, the user of the class doesn't know (or at least, has no business paying attention to the fact) that the object has one particular implementation or another. The interface to the class and its objects is exclusively via methods, and that's all the user of the class should ever play with. 上のように、そのクラスを使う人は、オブジェクトにある特定の実装があるか、 他の実装があるかを知りません(すくなくとも、その事実に注意を払うかは無関係です)。 クラスとそのオブジェクトへのインターフェースは、専らメソッド経由です。 そして、クラスを使う人はみんな、メソッドをいじるべきです。 =head2 コンストラクタと、インスタンスメソッド Still, I has to know what's in the object. And that someone is the class. It implements methods that the programmer uses to access the object. Here's how to implement the Person class using the standard hash-ref-as-an-object idiom. We'll make a class method called new() to act as the constructor, and three object methods called name(), age(), and peers() to get at per-object data hidden away in our anonymous hash. まだ、I<誰か>は、オブジェクトに何があるかを知る必要があります。 そして、その誰かとは、クラスです。クラスはプログラマが、オブジェクトにアクセスするのに使うメソッドを実装します。 ここに示すのは、標準的なオブジェクトのようにハッシュリファレンスを使うイディオムを使い、Personクラスに実装する方法です。 コンストラクタとして働くnew()というクラスメソッドを作りましょう。 そして、3つのオブジェクトメソッド、name()と、age()と、peers() を作り、 オブジェクトごとに、無名ハッシュにデータを隠すようにします。 package Person; use strict; ######################################################### ## オブジェクトのコンストラクタ (単純化したバージョン )## ######################################################### sub new { my $self = {}; $self->{NAME} = undef; $self->{AGE} = undef; $self->{PEERS} = []; bless($self); # 下を見て下さい return $self; } ##################################################### ## オブジェクトごとのデータにアクセスするメソッド ## ## ## ## 引数があれば、値をセットする。引数がなければ ## ## 値を返す。 ## ##################################################### sub name { my $self = shift; if (@_) { $self->{NAME} = shift } return $self->{NAME}; } sub age { my $self = shift; if (@_) { $self->{AGE} = shift } return $self->{AGE}; } sub peers { my $self = shift; if (@_) { @{ $self->{PEERS} } = @_ } return @{ $self->{PEERS} }; } 1; # require か、use を成功させるために We've created three methods to access an object's data, name(), age(), and peers(). These are all substantially similar. If called with an argument, they set the appropriate field; otherwise they return the value held by that field, meaning the value of that hash key. オブジェクトのデータにアクセスする3つのメソッド、name()、age()、peers()を、作りました。 これらは、実質は、すべて似たようなものです。 引数つきで呼べば、しかるべきフィールドに、値をセットし、引数がなければ、 そのフィールドに保持されている値を返します。ハッシュのキーの値を意味します。 =head2 将来を考える:よりよいコンストラクタ Even though at this point you may not even know what it means, someday you're going to worry about inheritance. (You can safely ignore this for now and worry about it later if you'd like.) To ensure that this all works out smoothly, you must use the double-argument form of bless(). The second argument is the class into which the referent will be blessed. By not assuming our own class as the default second argument and instead using the class passed into us, we make our constructor inheritable. たとえ、この時点でその意味することを知らなくてよくても、いつの日か継承に悩むことになるでしょう。 (お望みなら、今のところ継承を安全に無視し、後で、継承に悩むこともできます)。 継承が、全てスムーズにうまくいくことを保証するには、bless() に2つの引数を渡さなければいけません。 2番目の引数はクラスですが、リファレントを祝福(bless)するクラスです。 デフォルトでは、(訳註:2番目の引数を省略すると)2番目の引数として自分自身のクラスを想定します。 そのかわりに、(訳註:コンストラクタの第一引数に)渡されるクラスを使います。 こうすることで、コンストラクタは継承できるようになります。 While we're at it, let's make our constructor a bit more flexible. Rather than being uniquely a class method, we'll set it up so that it can be called as either a class method I an object method. That way you can say: さらに進めて、コンストラクタをもうちょっとフレキシブルにしましょう。 クラスメソッドだけではなくて、コンストラクタをクラスメソッド、I<または>、 オブジェクトメソッドとしても、呼べるようにしましょう。 $me = Person->new(); $him = $me->new(); To do this, all we have to do is check whether what was passed in was a reference or not. If so, we were invoked as an object method, and we need to extract the package (class) using the ref() function. If not, we just use the string passed in as the package name for blessing our referent. これをするには、渡されたものが、リファレンスであるかどうかをチェックすることだけです。 リファレンスであれば、オブジェクトメソッドとして呼び出し、 ref() 関数を使って、パッケージ(クラス)を抜き出さなければなりません。 リファレンスでなければ、渡された文字列をパッケージの名前として使い、 リファレントを祝福(bless)するだけです。 sub new { my $proto = shift; my $class = ref($proto) || $proto; my $self = {}; $self->{NAME} = undef; $self->{AGE} = undef; $self->{PEERS} = []; bless ($self, $class); return $self; } That's about all there is for constructors. These methods bring objects to life, returning neat little opaque bundles to the user to be used in subsequent method calls. これが、コンストラクタの全てです。これらのメソッドは、オブジェクトに命をもたらし、 きちんとした、小さくて、不可解な束をユーザに返し、次のメソッドの呼出しに使われます。 =head2 デストラクタ Every story has a beginning and an end. The beginning of the object's story is its constructor, explicitly called when the object comes into existence. But the ending of its story is the I, a method implicitly called when an object leaves this life. Any per-object clean-up code is placed in the destructor, which must (in Perl) be called DESTROY. 全ての話には、始まりがあり、終わりがあります。オブジェクトの話の始まりには、 コンストラクタがあり、オブジェクトが存在しはじめる時には、明示的にコンストラクタが呼ばれます。 オブジェクトの話の終わりは、I<デストラクタですが>、このメソッドは、 オブジェクトがその命を無くすときに暗黙のうちに呼ばれます。 オブジェクトごとの後かたづけのコードがデストラクタにあり、デストラクタは、 (Perlでは)DESTROYと呼ばれなければいけません。 If constructors can have arbitrary names, then why not destructors? Because while a constructor is explicitly called, a destructor is not. Destruction happens automatically via Perl's garbage collection (GC) system, which is a quick but somewhat lazy reference-based GC system. To know what to call, Perl insists that the destructor be named DESTROY. Perl's notion of the right time to call a destructor is not well-defined currently, which is why your destructors should not rely on when they are called. コンストラクタは恣意的な名前であるのに、なぜ、デストラクタは恣意的でないのでしょうか? その理由は、コンストラクタは、明示的に呼ばれますが、デストラクタはそうではないからです。 デストラクタの呼出しは、Perlのガベージコレクションシステム経由で、自動的に起こります。 素早いですが、幾分、怠惰なリファレンスに基づいた、ガベージコレクションシステムです。 呼ぶべきものが何かわかるように、Perl は、デストラクタが、DESTROYと名付けられることを、主張します。 Perlはデストラクタを呼ぶ適切な時期を考えますが、現在のところいつ呼ばれるかははっきり定義されていません。 このために、デストラクタは、それがいつ呼ばれるかを当てにすべきではありません。 Why is DESTROY in all caps? Perl on occasion uses purely uppercase function names as a convention to indicate that the function will be automatically called by Perl in some way. Others that are called implicitly include BEGIN, END, AUTOLOAD, plus all methods used by tied objects, described in L. なぜ、DESTORYはすべて大文字なのでしょう? Perlは、ときどき、慣例で全て大文字の関数名を使います。 この関数は、なんらかの方法でPerlによって自動的に呼ばれるかもしれないことを示します。 DESTROYの他に、暗黙のうちに呼ばれるものには、BEGINやENDやAUTOLOAD、加えて、 Lに書かれている、tieされたオブジェクトに使われる全てのメソッドなどが含まれます。 In really good object-oriented programming languages, the user doesn't care when the destructor is called. It just happens when it's supposed to. In low-level languages without any GC at all, there's no way to depend on this happening at the right time, so the programmer must explicitly call the destructor to clean up memory and state, crossing their fingers that it's the right time to do so. Unlike C++, an object destructor is nearly never needed in Perl, and even when it is, explicit invocation is uncalled for. In the case of our Person class, we don't need a destructor because Perl takes care of simple matters like memory deallocation. 本当によいオブジェクト指向プログラム言語では、ユーザは、デストラクタが呼ばれるときを気にしません。 起こるであろうときに、ただ、起きるのです。どんなガベージコレクションもまったくない、低レベルの言語では、 適切な時期にデストラクタが呼び出されることをまったく当てに出来ません。 そのため、プログラマは、明示的にデストラクタを呼び、メモリや状態の後かたづけをする必要があります。 C++ とは違って、オブジェクトのデストラクタは、ほとんど、Perlでは必要とされていません。 そして、デストラクタがあるときでさえ、明示的呼び出しは、ありません。 Personクラスの場合は、デストラクタを必要としません。 というのは、メモリの割り当て解除のような単純な問題は、Perlが面倒をみるからです。 The only situation where Perl's reference-based GC won't work is when there's a circularity in the data structure, such as: Perlのリファレンスに基づく、ガベージコレクションが働かない唯一の状況は、 データ構造に循環性があるときです。次のようなものです: $this->{WHATEVER} = $this; In that case, you must delete the self-reference manually if you expect your program not to leak memory. While admittedly error-prone, this is the best we can do right now. Nonetheless, rest assured that when your program is finished, its objects' destructors are all duly called. So you are guaranteed that an object I gets properly destroyed, except in the unique case of a program that never exits. (If you're running Perl embedded in another application, this full GC pass happens a bit more frequently--whenever a thread shuts down.) プログラムがメモリリークをしないことを期待するなら、この場合、自己参照を手動で削除しなければなりません。 明らかに、エラーを起こしやすい状態で、これは、ただ今できるベストなことです。 にもかかわらず、プログラムが終わるときに、そのオブジェクトのデストラクタが全て正式に呼ばれるので、 安全が保証されます。 そのため、次のことが保証されます。プログラムが終了していない唯一の場合をのぞいて、 オブジェクトが、I<最終的に>適切に、破壊されます。 (他のアプリケーションに、埋め込んでPerlを走らせているなら、この徹底したガベージコレクションの通過は、 普段より少々頻繁に - スレッドが終了する度に - 起こります)。 =head2 他のオブジェクトメソッド The methods we've talked about so far have either been constructors or else simple "data methods", interfaces to data stored in the object. These are a bit like an object's data members in the C++ world, except that strangers don't access them as data. Instead, they should only access the object's data indirectly via its methods. This is an important rule: in Perl, access to an object's data should I be made through methods. 今までに話しているメソッドは、コンストラクタか、他は、単純な"データメソッド"であり、 オブジェクトに蓄えられているデータへのインターフェースです。 これらのデータは、C++での、オブジェクトのデータメンバに少し似ています。 見知らぬ人がデータとして、オブジェクトのデータメンバにアクセスできないことを期待します。 その代わりに、オブジェクトのデータメンバにデータメソッド経由で、間接的にアクセスすべきです。 このことはPerlで、重要なルールです。Perlでは、オブジェクトのデータへのアクセスは、 メソッドを通してI<のみ>なされるべきです。 Perl doesn't impose restrictions on who gets to use which methods. The public-versus-private distinction is by convention, not syntax. (Well, unless you use the Alias module described below in L.) Occasionally you'll see method names beginning or ending with an underscore or two. This marking is a convention indicating that the methods are private to that class alone and sometimes to its closest acquaintances, its immediate subclasses. But this distinction is not enforced by Perl itself. It's up to the programmer to behave. Perlは、誰がどのメソッドを使えるかの制限を押しつけません。 パブリック と プライベート の違いは慣例によるもので、構文にはよりません。 (たぶん、L<変数としてのデータメンバ>に、下の方で記述するAliasモジュールを使わない場合は)。 メソッドの名前が一つか、2つののアンダースコアで始まっているか、終わっているものを見ることが あるでしょう。このマークは、慣例的に次のことを示します。そのメソッドがそのクラスだけ、 および、密接なその知合い、つまりサブクラスのプライベートなものであることを示します。 ですが、この区別はPerl自身によって、強制されてはいません。そう振る舞うことは、プログラマしだいです。 There's no reason to limit methods to those that simply access data. Methods can do anything at all. The key point is that they're invoked against an object or a class. Let's say we'd like object methods that do more than fetch or set one particular field. メソッドを単純なデータにアクセスするものだけに限定する理由はありません。 メソッドは、まったく、なんでもできます。キーポイントは、 メソッドは、オブジェクトかクラスを背景に呼び出されるということです。 たとえば、一つの特別なフィールドから値を持ってきたりセットしたりする以上のことをする オブジェクトメソッドを示しましょう。 sub exclaim { my $self = shift; return sprintf "Hi, I'm %s, age %d, working with %s", $self->{NAME}, $self->{AGE}, join(", ", @{$self->{PEERS}}); } Or maybe even one like this: または、次のようなもの: sub happy_birthday { my $self = shift; return ++$self->{AGE}; } Some might argue that one should go at these this way: 次のような方法でやると言う人もいるでしょう: sub exclaim { my $self = shift; return sprintf "Hi, I'm %s, age %d, working with %s", $self->name, $self->age, join(", ", $self->peers); } sub happy_birthday { my $self = shift; return $self->age( $self->age() + 1 ); } But since these methods are all executing in the class itself, this may not be critical. There are tradeoffs to be made. Using direct hash access is faster (about an order of magnitude faster, in fact), and it's more convenient when you want to interpolate in strings. But using methods (the external interface) internally shields not just the users of your class but even you yourself from changes in your data representation. ですが、これらのメソッドはクラス自身ですべて実行できるので、このことは重要ではないかもしれないません。 トレードオフがあります。直接なハッシュのアクセスはそうでない場合より速く(実際のところ、およそ桁違いに速く)、 文字列に手を加えたい時には、より便利です。ですが、メソッド(外部のインターフェース)を使うと、 内部的に、クラスを使う人だけでなく、クラスの作者自身が、データ表現に変更を加えることの盾にもなります。 =head1 クラスデータ What about "class data", data items common to each object in a class? What would you want that for? Well, in your Person class, you might like to keep track of the total people alive. How do you implement that? "クラスデータ" - クラスのそれぞれのオブジェクトに共通のデータアイテム - とはなんでしょう? 何のためにクラスデータが欲しいでしょう? たぶん、Person クラスでは、生きている人々の総数を追っておきたいでしょう。 You I make it a global variable called $Person::Census. But about only reason you'd do that would be if you I people to be able to get at your class data directly. They could just say $Person::Census and play around with it. Maybe this is ok in your design scheme. You might even conceivably want to make it an exported variable. To be exportable, a variable must be a (package) global. If this were a traditional module rather than an object-oriented one, you might do that. $Person::Census と呼ばれるグローバル変数でそういうことがI<できます>。 ですが、そのようにする唯一の理由は、人々が直接にクラスデータを得られるようにしたい場合です。 $Person::Census と言うだけで、それをいじることが出来ます。 あなたの考えでは、そういったことは構わないのかもしれません。 ひょっとすると、変数が持ち出されることさえ、望んでいるかもしれません。 持ち出されるのであれば、(パッケージの)グローバル変数でなければなりません。 これがオブジェクト指向的なモジュールでなく、伝統的なモジュールであれば、そうすればいいでしょう。 While this approach is expected in most traditional modules, it's generally considered rather poor form in most object modules. In an object module, you should set up a protective veil to separate interface from implementation. So provide a class method to access class data just as you provide object methods to access object data. クラス変数をパッケージのグローバル変数にするやり方は、ほとんどの伝統的なモジュールで、期待されています。 ですが、このやり方は、一般的に、ほとんどのオブジェクト指向のモジュールでは、むしろ下手なものと考えられています。 オブジェクト指向のモジュールでは、(訳註:データを)保護をするベールを設けて、実装とインターフェースを 分離します。ですから、オブジェクトデータにアクセスするオブジェクトメソッドを提供するのと同じように、 クラスデータにアクセスするクラスメソッドを提供します。 So, you I still keep $Census as a package global and rely upon others to honor the contract of the module and therefore not play around with its implementation. You could even be supertricky and make $Census a tied object as described in L, thereby intercepting all accesses. それで、まだ、$Census をパッケージのグローバル変数とし続けることが、I<できますし>、そして、 他人がモジュールの契約を支持し、そのために、その実装をいじくり回さないと信頼することがI<できます>。 かなりトリッキーに、Lに記述されているように、$Census を、tieされたオブジェクトにすることもできます。 But more often than not, you just want to make your class data a file-scoped lexical. To do so, simply put this at the top of the file: ですが、たいていは、クラスデータをファイルスコープのレキシカル変数にしたいと思います。 そうするためには、ファイルの上の方で、単純に次のものを置けばいいのです: my $Census = 0; Even though the scope of a my() normally expires when the block in which it was declared is done (in this case the whole file being required or used), Perl's deep binding of lexical variables guarantees that the variable will not be deallocated, remaining accessible to functions declared within that scope. This doesn't work with global variables given temporary values via local(), though. my() のスコープは、ふつう宣言されたブロックが終わったとき(この場合では、全てのファイルが必要とされ、使われているとき)が 期限ですが、Perlのレキシカル変数の深い束縛は、 そのスコープ内で宣言された関数にアクセスできる間は、変数が割り当て解除されないことを保証します。 このことは、local() にて、一時的な値を与えられたグローバル変数では、働きません。 Irrespective of whether you leave $Census a package global or make it instead a file-scoped lexical, you should make these changes to your Person::new() constructor: $Census をパッケージのグローバル変数のままにするか、代わりに、 ファイルスコープのレキシカル変数にするかどうかに関わりなく、 Person::new() コンストラクタに、次のような変更をするべきです。 sub new { my $proto = shift; my $class = ref($proto) || $proto; my $self = {}; $Census++; $self->{NAME} = undef; $self->{AGE} = undef; $self->{PEERS} = []; bless ($self, $class); return $self; } sub population { return $Census; } Now that we've done this, we certainly do need a destructor so that when Person is destroyed, the $Census goes down. Here's how this could be done: こうしたことで、もちろん、Personが壊れたときに、$Census を減らすために、 デストラクタが必要になります。次のようにします: sub DESTROY { --$Census } Notice how there's no memory to deallocate in the destructor? That's something that Perl takes care of for you all by itself. デストラクタ内で、割り当て解除するためのメモリがないことに、どのようにして気づくのでしょう? そのことは、Perl自身が面倒をみます。 Alternatively, you could use the Class::Data::Inheritable module from CPAN. 代わりに、CPANから、Class::Data::Inheritable モジュールを使うことも出来ます。 =head2 クラスデータにアクセスする It turns out that this is not really a good way to go about handling class data. A good scalable rule is that I. Otherwise you aren't building a scalable, inheritable class. The object must be the rendezvous point for all operations, especially from an object method. The globals (class data) would in some sense be in the "wrong" package in your derived classes. In Perl, methods execute in the context of the class they were defined in, I that of the object that triggered them. Therefore, namespace visibility of package globals in methods is unrelated to inheritance. クラスデータを絶えず取り扱うやり方は、本当によくないことがわかります。 十分に拡張的なルールは、I<オブジェクトメソッドから、直接にクラスデータを参照しない>ことです。 そうでなければ、拡張的な、継承できるクラスは作らないことです。オブジェクトは、全てのオペレーションのために、 ランデブーポイントにいなければなりません。特に、とりわけオブジェクトメソッドからは。 グローバル変数(クラスデータ)は、ある意味で、派生クラスの中で、"間違った"パッケージにあります。 Perlでは、メソッドはメソッドが定義されたクラス内のコンテキストで実行するのであり、 メソッドが動かされたオブジェクトのコンテキストではI<ありません>。 そのために、名前空間 - メソッド内で、目に見えるパッケージのグローバル変数の - は、継承と無関係です。 Got that? Maybe not. Ok, let's say that some other class "borrowed" (well, inherited) the DESTROY method as it was defined above. When those objects are destroyed, the original $Census variable will be altered, not the one in the new class's package namespace. Perhaps this is what you want, but probably it isn't. その名前空間を得られるでしょうか? たぶん、無理です。よし、たとえば、他のクラスが、 上で定義されているような(訳註:Personクラスの)DESTORYメソッドを、(たぶん継承されて)"借りた"としましょう。 これらの他のクラスのオブジェクトが破壊されたら、オリジナルの $Census 変数は変化させられます。 新しいクラスのパッケージの名前空間の$Censusではありません。 ひょっとしたら、このことは、あなたの望むものかもしれませんが、十中八九違うでしょう。 Here's how to fix this. We'll store a reference to the data in the value accessed by the hash key "_CENSUS". Why the underscore? Well, mostly because an initial underscore already conveys strong feelings of magicalness to a C programmer. It's really just a mnemonic device to remind ourselves that this field is special and not to be used as a public data member in the same way that NAME, AGE, and PEERS are. (Because we've been developing this code under the strict pragma, prior to perl version 5.004 we'll have to quote the field name.) これを修正する方法があります。ハッシュのキー"_CENSUS" で、アクセスされる値のデータに リファレンスを蓄えます。なぜアンダースコアをつけるかって? たぶん、たいてい、最初のアンダースコアは、いつもCプログラマに不思議な感覚を伝えるからです。 このフィールドが、特殊であり、NAMEや、AGEやPEERSと同じようなパブリックなデータメンバではないということを 思い出させる、たんなる、記憶を助ける工夫です。 (このコードは、strictプラグマをつけて、開発しているので、perl 5.004以前なら、フィールド名をクォートしないといけないでしょう) sub new { my $proto = shift; my $class = ref($proto) || $proto; my $self = {}; $self->{NAME} = undef; $self->{AGE} = undef; $self->{PEERS} = []; # "private" data $self->{"_CENSUS"} = \$Census; bless ($self, $class); ++ ${ $self->{"_CENSUS"} }; return $self; } sub population { my $self = shift; if (ref $self) { return ${ $self->{"_CENSUS"} }; } else { return $Census; } } sub DESTROY { my $self = shift; -- ${ $self->{"_CENSUS"} }; } =head2 デバッグメソッド It's common for a class to have a debugging mechanism. For example, you might want to see when objects are created or destroyed. To do that, add a debugging variable as a file-scoped lexical. For this, we'll pull in the standard Carp module to emit our warnings and fatal messages. That way messages will come out with the caller's filename and line number instead of our own; if we wanted them to be from our own perspective, we'd just use die() and warn() directly instead of croak() and carp() respectively. クラスにデバッグのメカニズムがあるのは、一般的です。たとえば、 オブジェクトが作られるか、破壊される時に、(訳註:デバッグ情報を)見たいでしょう。 そうするためには、デバッグの値をファイルスコープのレキシカル変数に加えます。 このために、警告と致命的なメッセージを発する標準のCarpモジュールを呼びましょう。 この方法により、自分自身のメーッセージの代わりにcallerのファイル名と行数と一緒に出ます; もし、自分自身の観点から、警告や致命的なメッセージが欲しいのなら、 croak() の代わりに、ただ、die() と warn() を、直接に使いましょう。 use Carp; my $Debugging = 0; Now add a new class method to access the variable. さて、新しいクラスメソッドに、変数のアクセスを加えましょう。 sub debug { my $class = shift; if (ref $class) { confess "Class method called as object method" } unless (@_ == 1) { confess "usage: CLASSNAME->debug(level)" } $Debugging = shift; } Now fix up DESTROY to murmur a bit as the moribund object expires: さて、DESTROYに手を入れて、 消滅しかけているオブジェクトが失効する時にちょっと文句を言うようにしましょう: sub DESTROY { my $self = shift; if ($Debugging) { carp "Destroying $self " . $self->name } -- ${ $self->{"_CENSUS"} }; } One could conceivably make a per-object debug state. That way you could call both of these: ひょっとしたら、オブジェクトごとに、デバッグ状態を持ちたいかも知れません。 両方ともできるを方法があります: Person->debug(1); # クラス全部 $him->debug(1); # このオブジェクトだけ To do so, we need our debugging method to be a "bimodal" one, one that works on both classes I objects. Therefore, adjust the debug() and DESTROY methods as follows: こうするためには、デバッグメソッドは、"二頂の"メソッドでなければなりません。 クラスI<と>オブジェクトの両方で動くメソッドです。 そのため、debug()と、DESTORYメソッドを次のように、調整します: sub debug { my $self = shift; confess "usage: thing->debug(level)" unless @_ == 1; my $level = shift; if (ref($self)) { $self->{"_DEBUG"} = $level; # just myself } else { $Debugging = $level; # whole class } } sub DESTROY { my $self = shift; if ($Debugging || $self->{"_DEBUG"}) { carp "Destroying $self " . $self->name; } -- ${ $self->{"_CENSUS"} }; } What happens if a derived class (which we'll call Employee) inherits methods from this Person base class? Then C<< Employee->debug() >>, when called as a class method, manipulates $Person::Debugging not $Employee::Debugging. (Employeeと呼ばれる)派生クラスが、Person 基底クラスからメソッドを継承していると、 何が起きるでしょうか? C<< Employee->debug() >> は、クラスメソッドとして呼ばれた場合、 $Employee::Debugging ではなく、 $Person::Debugging を操作します。 =head2 クラスのデストラクタ The object destructor handles the death of each distinct object. But sometimes you want a bit of cleanup when the entire class is shut down, which currently only happens when the program exits. To make such a I, create a function in that class's package named END. This works just like the END function in traditional modules, meaning that it gets called whenever your program exits unless it execs or dies of an uncaught signal. For example, オブジェクトのデストラクタは、それぞれの別個のオブジェクトごとの死を取り扱います。 しかし、クラス全体のシャットダウン - これは現在のところプログラムが終了した時に起こる - ちょっとした掃除が欲しいときもあります。そのようなI<クラスのデストラクタ>を作るために、 そのクラスパッケージの中に、ENDと名付けられる関数を作ります。 ENDの働きは、伝統的なモジュールのEND関数とちょうど似ています。 プログラムが実行されないか、とらえられないシグナルで死んで、プログラムが終了したときにいつでも呼ばれます。 sub END { if ($Debugging) { print "All persons are going away now.\n"; } } When the program exits, all the class destructors (END functions) are be called in the opposite order that they were loaded in (LIFO order). プログラムが終了しとき、全てのクラスデストラクタ(END関数)は、 クラスがロードされたのと反対の順番(LIFOの順番)で呼ばれます。 =head2 インターフェースをドキュメントにする And there you have it: we've just shown you the I of this Person class. Its I would be its documentation. Usually this means putting it in pod ("plain old documentation") format right there in the same file. In our Person example, we would place the following docs anywhere in the Person.pm file. Even though it looks mostly like code, it's not. It's embedded documentation such as would be used by the pod2man, pod2html, or pod2text programs. The Perl compiler ignores pods entirely, just as the translators ignore code. Here's an example of some pods describing the informal interface: そして、ドキュメントがあります:今まで、このPersonクラスのI<実装>を見せています。 PersonクラスのI<インターフェース>は、Personクラスのドキュメントになります。 ふつう、このことは、同じファイルに、pod("plain old documentation")のフォーマットでドキュメントを置く ことを意味します。Personの例では、Person.pm ファイルの中に、下に続くドキュメントを配置します。 たとえ、このドキュメントがほとんどコードに見えても、違います。 これは、埋め込まれたドキュメントであり、pod2man や、pod2html や、pod2text プログラムで使われます。 Perlのコンパイラは、podをまったく無視します。ちょうど、翻訳者がコードを無視するのと同じです。 略式のインターフェースを記述するpod の例です: =head1 NAME Person - class to implement people =head1 SYNOPSIS use Person; ################# # class methods # ################# $ob = Person->new; $count = Person->population; ####################### # object data methods # ####################### ### get versions ### $who = $ob->name; $years = $ob->age; @pals = $ob->peers; ### set versions ### $ob->name("Jason"); $ob->age(23); $ob->peers( "Norbert", "Rhys", "Phineas" ); ######################## # other object methods # ######################## $phrase = $ob->exclaim; $ob->happy_birthday; =head1 DESCRIPTION The Person class implements dah dee dah dee dah.... That's all there is to the matter of interface versus implementation. A programmer who opens up the module and plays around with all the private little shiny bits that were safely locked up behind the interface contract has voided the warranty, and you shouldn't worry about their fate. インターフェース対実装の問題があります。 モジュールを開いて、インターフェースの契約の後ろにある、 安全に鍵をかけられた、全てのプライベートなほのかに輝く小さなものを、 いじくりまわすようなプログラマには、保証が無効になります。 彼らの運命を気に病むべきではありません。 =head1 集約(Aggregation) Suppose you later want to change the class to implement better names. Perhaps you'd like to support both given names (called Christian names, irrespective of one's religion) and family names (called surnames), plus nicknames and titles. If users of your Person class have been properly accessing it through its documented interface, then you can easily change the underlying implementation. If they haven't, then they lose and it's their fault for breaking the contract and voiding their warranty. 後になって、よりよい名前を実装するために、クラスを変えたくなったとしましょう。 たぶん、ファーストネーム(その人の宗教にかかわりなく、クリスチャンネームと呼ばれる)と ファミリーネーム(名字と呼ばれる)の両方と、それに加えて、ニックネームと称号もサポートしたくなったとします。 もし、Person クラスを使う人が、このドキュメントに書かれたインターフェースを通して、 適切にアクセスしていれば、簡単にその下にある実装を変更することが出来ます。 もし、そうでなければ、Personクラスを使う人は損をします。契約を破り、保証を失効したむくいです。 To do this, we'll make another class, this one called Fullname. What's the Fullname class look like? To answer that question, you have to first figure out how you want to use it. How about we use it this way: 次のようにして、他のクラスを作ります。このクラスは、Fullname というクラスです。 Fullname クラスとは、どのようなものでしょうか? その質問に答えるには、 最初に、それをどのように使いたいかを把握しなければなりません。 Fullname クラスは次のように使います: $him = Person->new(); $him->fullname->title("St"); $him->fullname->christian("Thomas"); $him->fullname->surname("Aquinas"); $him->fullname->nickname("Tommy"); printf "His normal name is %s\n", $him->name; printf "But his real name is %s\n", $him->fullname->as_string; Ok. To do this, we'll change Person::new() so that it supports a full name field this way: よし。こうするために、Person::new() をフルネームのフィールドをサポートするように、 次のように変えます: sub new { my $proto = shift; my $class = ref($proto) || $proto; my $self = {}; $self->{FULLNAME} = Fullname->new(); $self->{AGE} = undef; $self->{PEERS} = []; $self->{"_CENSUS"} = \$Census; bless ($self, $class); ++ ${ $self->{"_CENSUS"} }; return $self; } sub fullname { my $self = shift; return $self->{FULLNAME}; } Then to support old code, define Person::name() this way: それから、古いコードをサポートするために、Person::name() を次のように定義します: sub name { my $self = shift; return $self->{FULLNAME}->nickname(@_) || $self->{FULLNAME}->christian(@_); } Here's the Fullname class. We'll use the same technique of using a hash reference to hold data fields, and methods by the appropriate name to access them: Fullnameクラスがあります。データフィールドを持つのにハッシュリファレンスを使ったのと同じテクニックを使い、 データフィールドにアクセスするのに適切な名前でメソッドを使います: package Fullname; use strict; sub new { my $proto = shift; my $class = ref($proto) || $proto; my $self = { TITLE => undef, CHRISTIAN => undef, SURNAME => undef, NICK => undef, }; bless ($self, $class); return $self; } sub christian { my $self = shift; if (@_) { $self->{CHRISTIAN} = shift } return $self->{CHRISTIAN}; } sub surname { my $self = shift; if (@_) { $self->{SURNAME} = shift } return $self->{SURNAME}; } sub nickname { my $self = shift; if (@_) { $self->{NICK} = shift } return $self->{NICK}; } sub title { my $self = shift; if (@_) { $self->{TITLE} = shift } return $self->{TITLE}; } sub as_string { my $self = shift; my $name = join(" ", @$self{'CHRISTIAN', 'SURNAME'}); if ($self->{TITLE}) { $name = $self->{TITLE} . " " . $name; } return $name; } 1; Finally, here's the test program: 最後に、テストプログラムです: #!/usr/bin/perl -w use strict; use Person; sub END { show_census() } sub show_census () { printf "Current population: %d\n", Person->population; } Person->debug(1); show_census(); my $him = Person->new(); $him->fullname->christian("Thomas"); $him->fullname->surname("Aquinas"); $him->fullname->nickname("Tommy"); $him->fullname->title("St"); $him->age(1); printf "%s is really %s.\n", $him->name, $him->fullname; printf "%s's age: %d.\n", $him->name, $him->age; $him->happy_birthday; printf "%s's age: %d.\n", $him->name, $him->age; show_census(); =head1 継承 Object-oriented programming systems all support some notion of inheritance. Inheritance means allowing one class to piggy-back on top of another one so you don't have to write the same code again and again. It's about software reuse, and therefore related to Laziness, the principal virtue of a programmer. (The import/export mechanisms in traditional modules are also a form of code reuse, but a simpler one than the true inheritance that you find in object modules.) オブジェクト指向プログラミングのシステムは、全て、継承の考えをサポートします。 継承は、一つのクラスが他のクラスの上におんぶすることを意味します。 ですから、同じコードをくり返し、くり返し、書かなくて済みます。 つまり、ソフトウェアの再利用です。そして、それゆえ、不精 - プログラマの重要な美徳 - に関連します。 (伝統的なモジュールのimport/export メカニズムもまた、コードの再利用の形です。ですが、 オブジェクトモジュールに見られる、本当の継承よりも単純なものです) Sometimes the syntax of inheritance is built into the core of the language, and sometimes it's not. Perl has no special syntax for specifying the class (or classes) to inherit from. Instead, it's all strictly in the semantics. Each package can have a variable called @ISA, which governs (method) inheritance. If you try to call a method on an object or class, and that method is not found in that object's package, Perl then looks to @ISA for other packages to go looking through in search of the missing method. 継承の文法は、時に、言語の核に組み込まれていることがあれば、そうでないときもあります。 Perlは、一つのクラス(や、複数のクラス)から、継承するのに特別な文法はありません。 その代わりに、意味論においては、全て厳しい。それぞれのパッケージには、 @ISAと呼ばれる変数があり、@ISAは、(メソッド)継承を治めるものです。 もし、オブジェクトかクラスで、メソッドを呼ぼうとして、 そのメソッドが、そのオブジェクトのパッケージには見付からないと、 Perlは、見付からないメソッドを検索するさいに、@ISAを見て、他のパッケージを探しに行きます。 Like the special per-package variables recognized by Exporter (such as @EXPORT, @EXPORT_OK, @EXPORT_FAIL, %EXPORT_TAGS, and $VERSION), the @ISA array I be a package-scoped global and not a file-scoped lexical created via my(). Most classes have just one item in their @ISA array. In this case, we have what's called "single inheritance", or SI for short. 特別なパッケージ毎の、Exporterで、見分けれる変数(@EXPORT,@EXPORT_OK,@EXPORT_FAIL,%EXPORT_TAGS,$VERSION) のように、@ISA配列は、パッケージスコープのグローバル変数でI<なければならず>、 my()で作られるファイルスコープのレキシカル変数であってはI<いけません>。 ほとんどのクラスで、@ISA配列には一つのものしかありません。 このことは、"単一継承"と呼ばれるものです。省略して、SIとも呼ばれます。 Consider this class: このクラスについて、考えてみましょう: package Employee; use Person; @ISA = ("Person"); 1; Not a lot to it, eh? All it's doing so far is loading in another class and stating that this one will inherit methods from that other class if need be. We have given it none of its own methods. We rely upon an Employee to behave just like a Person. 多くないでしょ? 今のところ、このEmployeeクラスがするのは、他のクラスをロードすることと、 必要なら、その、他のクラスからメソッドを継承することを始めることだけです。 Employeeクラスには、それ自身のメソッドを与えてはいません。 ですが、Employeeクラスに、ちょうどPersonクラスのような振る舞いを当てにします。 Setting up an empty class like this is called the "empty subclass test"; that is, making a derived class that does nothing but inherit from a base class. If the original base class has been designed properly, then the new derived class can be used as a drop-in replacement for the old one. This means you should be able to write a program like this: このような空のクラスを作ることは、"空のサブクラステスト"と呼ばれます。 これは、基底クラスから継承する以外には、なにもしない派生クラスを作ることです。 オリジナルの基底クラスは、適切に設計されていれば、 新しい派生クラスは、古いものの差し込み式の置換として、使われます。 このことが意味するのは、次のようにプログラムを書けるということです: use Employee; my $empl = Employee->new(); $empl->name("Jason"); $empl->age(23); printf "%s is age %d.\n", $empl->name, $empl->age; By proper design, we mean always using the two-argument form of bless(), avoiding direct access of global data, and not exporting anything. If you look back at the Person::new() function we defined above, we were careful to do that. There's a bit of package data used in the constructor, but the reference to this is stored on the object itself and all other methods access package data via that reference, so we should be ok. 適切な設計によって、そうできます。適切な設計とは、常にbless()に、2つの引数を与え、 グローバルなデータに直接アクセスするのを避け、何もexportしない設計のことです。 上の方で定義しているPerson::new()関数を見返したら、そうするように注意しています。 コンストラクタで使われるパッケージデータが少しありますが、 パッケージデータへのリファレンスが、オブジェクト自身に、蓄えられており、他の全てのメソッドは そのリファレンスを通して、パッケージデータにアクセスします。それで、よしとすべきです。 What do we mean by the Person::new() function -- isn't that actually a method? Well, in principle, yes. A method is just a function that expects as its first argument a class name (package) or object (blessed reference). Person::new() is the function that both the C<< Person->new() >> method and the C<< Employee->new() >> method end up calling. Understand that while a method call looks a lot like a function call, they aren't really quite the same, and if you treat them as the same, you'll very soon be left with nothing but broken programs. First, the actual underlying calling conventions are different: method calls get an extra argument. Second, function calls don't do inheritance, but methods do. Person::new() 関数で、意図したこと -- 実際にはメソッドではないですか? たぶん、原則的には、メソッドです。メソッドは、ちょうど、 その最初の引数に、クラスの名前(パッケージ)か、オブジェクト(blessされたリファレンス) を期待する関数です。Person::new()は、結局、C<< Person->new() >> メソッドと C<< Employee->new() >> メソッドの両方が呼んでいる関数です。 メソッド呼び出しが関数呼び出しによく似ていながら、本当は、まったく同じではなく、 この2つを同じものとして扱うなら、すぐに壊れたプラグラムしか残されないことを理解してください。 第一に、現実に、基礎となっている呼び出しの慣例が違っています:メソッド呼び出しは、 特別な引数を得ます。第二に、関数呼び出しは継承をしませんが、メソッド呼び出しは継承をします。 メソッド呼出 結果として、関数呼び出し ----------- ------------------------ Person->new() Person::new("Person") Employee->new() Person::new("Employee") So don't use function calls when you mean to call a method. ですので、メソッドを呼ぼうとしているときに関数呼び出しを使わないでください。 If an employee is just a Person, that's not all too very interesting. So let's add some other methods. We'll give our employee data fields to access their salary, their employee ID, and their start date. 従業員が、ただの、Personだったら、それはあまり面白くありません。 さあ、他のメソッドを追加しましょう。従業員に、データフィールドを設けて、 従業員の給与や、従業員ID や、入社日 にアクセスしましょう。 If you're getting a little tired of creating all these nearly identical methods just to get at the object's data, do not despair. Later, we'll describe several different convenience mechanisms for shortening this up. Meanwhile, here's the straight-forward way: これらのオブジェクトのデータを取得するような、ほとんど同じメソッドたちを作るのに ちょっと飽きたとしても、落胆しないでください。後で、こういった作業を短縮するための、 いくつかの種々の便利なメカニズムについて説明します。 その逆に、単純なやりかたは次のものです: sub salary { my $self = shift; if (@_) { $self->{SALARY} = shift } return $self->{SALARY}; } sub id_number { my $self = shift; if (@_) { $self->{ID} = shift } return $self->{ID}; } sub start_date { my $self = shift; if (@_) { $self->{START_DATE} = shift } return $self->{START_DATE}; } =head2 メソッドのオーバーライド What happens when both a derived class and its base class have the same method defined? Well, then you get the derived class's version of that method. For example, let's say that we want the peers() method called on an employee to act a bit differently. Instead of just returning the list of peer names, let's return slightly different strings. So doing this: 派生クラスとその基底クラスの両方が同じ名前のメソッドを定義したら、何が起きるでしょうか? たぶん、そのメソッドは派生クラスのもの(訳註:version)を得ます。 例えば、従業員で、peers()メソッドを呼ぶと、(訳註:Personとは、)少々違った動きをさせたいとしましょう。 同僚の名前のリストをただ返す代わりに、ちょっと違った文字列を返しましょう。次のようにします: $empl->peers("Peter", "Paul", "Mary"); printf "His peers are: %s\n", join(", ", $empl->peers); will produce: 次のようになります: His peers are: PEON=PETER, PEON=PAUL, PEON=MARY To do this, merely add this definition into the Employee.pm file: こうするためには、単に、この定義をEmployee.pm ファイルに加えるだけです。 sub peers { my $self = shift; if (@_) { @{ $self->{PEERS} } = @_ } return map { "PEON=\U$_" } @{ $self->{PEERS} }; } There, we've just demonstrated the high-falutin' concept known in certain circles as I. We've taken on the form and behaviour of an existing object, and then we've altered it to suit our own purposes. This is a form of Laziness. (Getting polymorphed is also what happens when the wizard decides you'd look better as a frog.) ここで、ちょうど、I<ポリモルフィズム>として広く知られている、大げさなコンセプトの デモンストレーションをしています。存在するオブジェクトの形と振るまいを担い、 われわれ自身の目的に適応するように、存在するオブジェクトを変更します。 これは、不精の形です。(ポリモルファイさせることは、魔法使いが、あなたを、蛙に 見せようと決めるときに起こることです)。 Every now and then you'll want to have a method call trigger both its derived class (also known as "subclass") version as well as its base class (also known as "superclass") version. In practice, constructors and destructors are likely to want to do this, and it probably also makes sense in the debug() method we showed previously. しばしば、派生クラス("サブクラス"としても知られるクラス)のもの(訳註:version)と その基底クラス("スーパークラス"としても知られるクラス)のもの(訳註:version)も同じように 両方をきっかけをメソッドに呼ばせたいでしょう。 実際に、コンストラクタとデストラクタは、そうすることを望んでいそうですし、 先にみた、debug() メソッドでは、十中八九、そうだとうなずけます。 To do this, add this to Employee.pm: そうするために、Employee.pm に次のものを加えます: use Carp; my $Debugging = 0; sub debug { my $self = shift; confess "usage: thing->debug(level)" unless @_ == 1; my $level = shift; if (ref($self)) { $self->{"_DEBUG"} = $level; } else { $Debugging = $level; # whole class } Person::debug($self, $Debugging); # don't really do this } As you see, we turn around and call the Person package's debug() function. But this is far too fragile for good design. What if Person doesn't have a debug() function, but is inheriting I debug() method from elsewhere? It would have been slightly better to say お分かりのように、(訳註:Employeeから)向きを変えて、Person パッケージの debug()関数を呼びます。 ですが、良い設計にとっては、こうするのは、ひじょーに、壊れやすいものです。 Personがdebug()関数を持っておらず、I<その>debug()メソッド を他のところから継承していたら、どうなるでしょう? 次のようにする方が、良いです。 Person->debug($Debugging); But even that's got too much hard-coded. It's somewhat better to say ですが、まだ、ハードコードしすぎです。次のようにする方が、良いです。 $self->Person::debug($Debugging); Which is a funny way to say to start looking for a debug() method up in Person. This strategy is more often seen on overridden object methods than on overridden class methods. これは、Person内で、debug()メソッドを探し始める楽しいやりかたです。 この作戦は、オーバーライドされたクラスメソッドよりも、 オーバーライドされたオブジェクトメソッドで、よく見ます。 There is still something a bit off here. We've hard-coded our superclass's name. This in particular is bad if you change which classes you inherit from, or add others. Fortunately, the pseudoclass SUPER comes to the rescue here. 少しのものがまだ、あります。スーパークラスの名前をハードコードしています。 継承するクラスを変えるか、他のものを加えたら、このことは、特に、悪いです。 幸運なことに、仮名クラスのSUPERが、ここで、助けになります。 $self->SUPER::debug($Debugging); This way it starts looking in my class's @ISA. This only makes sense from I a method call, though. Don't try to access anything in SUPER:: from anywhere else, because it doesn't exist outside an overridden method call. こうすると、自分のクラスの@ISAをのぞき始ます。これは、メソッドコールI<内>から意味をなすだけです。 他のどこからも、SUPER::の何にも、アクセスしようとしないでください。 というのは、上書きされたメソッド呼出の外側には存在しないからです。 Things are getting a bit complicated here. Have we done anything we shouldn't? As before, one way to test whether we're designing a decent class is via the empty subclass test. Since we already have an Employee class that we're trying to check, we'd better get a new empty subclass that can derive from Employee. Here's one: 事態は、ちょっと複雑になってきています。してはならないことをしたでしょうか? これまでのように、まともなクラスかどうかをテストする一つの方法は、 空のサブクラスを経由するテストです。 すでに、チェックしているEmployeeクラスがあるので、 Employeeから、新しい空のサブクラスを生成できます。次のものです: package Boss; use Employee; # :-) @ISA = qw(Employee); And here's the test program: テストプログラムです: #!/usr/bin/perl -w use strict; use Boss; Boss->debug(1); my $boss = Boss->new(); $boss->fullname->title("Don"); $boss->fullname->surname("Pichon Alvarez"); $boss->fullname->christian("Federico Jesus"); $boss->fullname->nickname("Fred"); $boss->age(47); $boss->peers("Frank", "Felipe", "Faust"); printf "%s is age %d.\n", $boss->fullname, $boss->age; printf "His peers are: %s\n", join(", ", $boss->peers); Running it, we see that we're still ok. If you'd like to dump out your object in a nice format, somewhat like the way the 'x' command works in the debugger, you could use the Data::Dumper module from CPAN this way: 実行すると、まだ、大丈夫です。素敵なフォーマットで、デバッガーで 'x'コマンドを働かせる方法のように、 オブジェクトをダンプしたいなら、CPANから、Data::Dumplerモジュールを次のように使うことが出来ます: use Data::Dumper; print "Here's the boss:\n"; print Dumper($boss); Which shows us something like this: 次のようなものを見せます: Here's the boss: $VAR1 = bless( { _CENSUS => \1, FULLNAME => bless( { TITLE => 'Don', SURNAME => 'Pichon Alvarez', NICK => 'Fred', CHRISTIAN => 'Federico Jesus' }, 'Fullname' ), AGE => 47, PEERS => [ 'Frank', 'Felipe', 'Faust' ] }, 'Boss' ); Hm.... something's missing there. What about the salary, start date, and ID fields? Well, we never set them to anything, even undef, so they don't show up in the hash's keys. The Employee class has no new() method of its own, and the new() method in Person doesn't know about Employees. (Nor should it: proper OO design dictates that a subclass be allowed to know about its immediate superclass, but never vice-versa.) So let's fix up Employee::new() this way: ふーむ、何かがなくなっています。給与、入社日、IDフィールドはどうでしょうか? たぶん、それらに、何も、undefさえもセットしていません。そのため、ハッシュのキーに、 それらが見えなかったのです。Employeeクラスは、それ自身のnew() メソッドがありません。 Personのnew()メソッドは、Employeeについて知りません。 (また、そうすべきでもありません:適切なオブジェクト指向設計はサブクラスがそのすぐ上のスーパークラスについて 知っていてもよいと指示しています。ですが、その逆は同様ではありません)。 では、Employee::new()を次のように、しましょう: sub new { my $proto = shift; my $class = ref($proto) || $proto; my $self = $class->SUPER::new(); $self->{SALARY} = undef; $self->{ID} = undef; $self->{START_DATE} = undef; bless ($self, $class); # reconsecrate return $self; } Now if you dump out an Employee or Boss object, you'll find that new fields show up there now. EmployeeかBossブジェクトをダンプしたら、今度は、新しいフィールドがそこに 現れるでしょう。 =head2 多重継承 Ok, at the risk of confusing beginners and annoying OO gurus, it's time to confess that Perl's object system includes that controversial notion known as multiple inheritance, or MI for short. All this means is that rather than having just one parent class who in turn might itself have a parent class, etc., that you can directly inherit from two or more parents. It's true that some uses of MI can get you into trouble, although hopefully not quite so much trouble with Perl as with dubiously-OO languages like C++. よし。初心者もオブジェクト指向のエキスパートも混乱させる危険をおかしても、白状する時がきました。 Perlのオブジェクトシステムは、多重継承、または、略してMIとして知られる、賛否両論の考えを含んでいます。 これが意味するのは、次のことで全てです。 ただ一つの親クラス - 今度は、それ自身が親クラスやそのほかを持っている - を持つのではなく、 2つ以上の親クラスを持つことが出来ることです。多重継承の使うことで、トラブルに見まわれることもありますが、 C++のようなあいまいなオブジェクト指向言語のPerl では、うまくいけば、たいした問題にはならないこともあります。 The way it works is actually pretty simple: just put more than one package name in your @ISA array. When it comes time for Perl to go finding methods for your object, it looks at each of these packages in order. Well, kinda. It's actually a fully recursive, depth-first order. Consider a bunch of @ISA arrays like this: 多重継承のやりかたは、実際、非常に簡単です:@ISA配列に二つ以上のパッケージ名を置けばいいだけです。 Perlが、オブジェクトのために、メソッドを見つけに行く時がきたら、 順麺に@ISAのパッケージをそれそれ見ます。 えっと、かなり. 完全にリカーシブで、depth-firstの順番です。 次のような@ISA配列の組合せを考えてください: @First::ISA = qw( Alpha ); @Second::ISA = qw( Beta ); @Third::ISA = qw( First Second ); If you have an object of class Third: Third クラスのオブジェクトがあるとすると、 my $ob = Third->new(); $ob->spin(); How do we find a spin() method (or a new() method for that matter)? Because the search is depth-first, classes will be looked up in the following order: Third, First, Alpha, Second, and Beta. spin()メソッド(または、さらに言えば、new())をどのように見つけるのでしょうか? 検索は、depth-firstなので、クラスは次の順番で調べられます: Third First Alpha Second Beta の順です。 In practice, few class modules have been seen that actually make use of MI. One nearly always chooses simple containership of one class within another over MI. That's why our Person object I a Fullname object. That doesn't mean it I one. 実際には、多重継承が使われているクラスモジュールは、ほとんどみかけません。 ほとんどいつも、多重継承の上の別のものの中の、 単純な一つのクラスを積んだコンテナ船を選びます。 Person オブジェクトは、Fullname オブジェクトをI<積んだ>オブジェクトだからです。 それが一つでI<あった>というわけではありません。(訳註:謎) However, there is one particular area where MI in Perl is rampant: borrowing another class's class methods. This is rather common, especially with some bundled "objectless" classes, like Exporter, DynaLoader, AutoLoader, and SelfLoader. These classes do not provide constructors; they exist only so you may inherit their class methods. (It's not entirely clear why inheritance was done here rather than traditional module importation.) しかしながら、Perlでの多重継承が見境のない、一つの特別な領域があります: 他のクラスのクラスメソッドを借りて来ることです。このことは、幾分普及しており、 バンドルされている"オブジェクトのない"クラスで特にそうです。 Exporterや、DynaLoaderや、AutoLoaderや、SelfLoaderがそうです。 これらのクラスは、コンストラクタを提供しません。これらのクラスは、 (訳註:他のクラスから)クラスメソッドを継承するかもしれないので、存在しています。 For example, here is the POSIX module's @ISA: たとえば、POSIXモジュールの@ISAは次のようになっています: package POSIX; @ISA = qw(Exporter DynaLoader); The POSIX module isn't really an object module, but then, neither are Exporter or DynaLoader. They're just lending their classes' behaviours to POSIX. POSIXモジュールは、実際には、オブジェクトモジュールではありません。ですが、 Exporter も DynaLoaderも、そうです。 Exporderと、DynaLoader クラスは、クラスメソッドの振るまいをPOSIXに、貸しているだけです。 Why don't people use MI for object methods much? One reason is that it can have complicated side-effects. For one thing, your inheritance graph (no longer a tree) might converge back to the same base class. Although Perl guards against recursive inheritance, merely having parents who are related to each other via a common ancestor, incestuous though it sounds, is not forbidden. What if in our Third class shown above we wanted its new() method to also call both overridden constructors in its two parent classes? The SUPER notation would only find the first one. Also, what about if the Alpha and Beta classes both had a common ancestor, like Nought? If you kept climbing up the inheritance tree calling overridden methods, you'd end up calling Nought::new() twice, which might well be a bad idea. なぜ、オブジェクトメソッドに、多重継承が使われないのでしょうか? 理由の一つは、複雑な副作用がありうるからです。 まず一つ例をあげると、継承のグラフ(ツリーではなく)が、同じ基底クラスにもどって 集中します。Perlは、リカーシブな継承に対して防御していますが、 単に、共通の祖先を通して、お互いに関連している親を持つことは、近親相姦に思えても、 禁止されていません。もし、先ほど見たThirdクラスで、new()メソッドが、 Thirdクラスの2つの親クラスで、オーバーライドされたコンストラクタを両方呼ぶとしたら、 どうなるんでしょう? SUPER表記は、最初の一つしか見つけません。 Alpha と Betaクラスの両方が、共通の祖先、たとえば Nought クラスを持っていたらどうでしょうか? オーバーライドされたメソッドを呼ぶ継承ツリーを登り続けるなら、結局、Nought::new() を二度呼ぶことになります。 たぶん、それは、悪い考えでしょう。 =head2 UNIVERSAL: 全てのオブジェクトの根っこ Wouldn't it be convenient if all objects were rooted at some ultimate base class? That way you could give every object common methods without having to go and add it to each and every @ISA. Well, it turns out that you can. You don't see it, but Perl tacitly and irrevocably assumes that there's an extra element at the end of @ISA: the class UNIVERSAL. In version 5.003, there were no predefined methods there, but you could put whatever you felt like into it. 全てのオブジェクトが、いくつかの根本的な基底クラスに根付いていたら、便利でしょうか? すべてのオブジェクトに共通のメソッドを与えるのに、それぞれの@ISAにクラスを加えずにできる方法です。 それで、そうできることがわかります。それを見ることはありませんが、Perlは、それとなく、決定的に、 @ISAの終わりに、特別な要素があることを想定しています:UNIVERSALクラスです。 5.003では、UNIVERSALクラスにあらかじめ定義されているメソッドは、ありませんでしたが、 UNIVERSALクラスにいれたいようなものは、なんでも、置くことが出来ました。 However, as of version 5.004 (or some subversive releases, like 5.003_08), UNIVERSAL has some methods in it already. These are builtin to your Perl binary, so they don't take any extra time to load. Predefined methods include isa(), can(), and VERSION(). isa() tells you whether an object or class "is" another one without having to traverse the hierarchy yourself: しかし、5.004(または、5.003_08のような、いくつかの破棄的なリリース)より、 UNIVERSALには、既にいくつかのメソッドがあります。これらのメソッドは、 Perl バイナリに組み込まれており、そのため、それらをロードするのに、余計な時間はかかりません。 あらかじめ定義されているメソッドは、isa() 、can()、VERSION()です。 isa()は、オブジェクトかクラスが階層構造を横断することなく、別のクラス"である"かどうかを教えます。 $has_io = $fd->isa("IO::Handle"); $itza_handle = IO::Socket->isa("IO::Handle"); The can() method, called against that object or class, reports back whether its string argument is a callable method name in that class. In fact, it gives you back a function reference to that method: can()メソッドは、オブジェクトかクラスに対して呼ばれて、その文字列の引数が そのクラスで、呼ぶことの出来るメソッドかどうかを帰って報告します。 実際、そのメソッドに関数のリファレンスを返します: $his_print_method = $obj->can('as_string'); Finally, the VERSION method checks whether the class (or the object's class) has a package global called $VERSION that's high enough, as in: 最後に、VERSIONメソッドは、クラス(または、オブジェクトのクラス)が、 $VERSIONと呼ばれるパッケージのグローバル変数が十分に高いかどうかをチェックします。次のように: Some_Module->VERSION(3.0); $his_vers = $ob->VERSION(); However, we don't usually call VERSION ourselves. (Remember that an all uppercase function name is a Perl convention that indicates that the function will be automatically used by Perl in some way.) In this case, it happens when you say しかし、ふつう、VERSIONを自分自身には呼びません。(次のことを覚えておいてください。 すべての大文字の関数名は、Perlの慣例で、その関数が、なんらかの方法で、 Perlによって自動的に使われるだろうということを、示しています。) このケースでは、次のようにすると、おなじことが起こります: use Some_Module 3.0; If you wanted to add version checking to your Person class explained above, just add this to Person.pm: 上に説明したPersonクラスでバージョンのチェックを加えたいなら、 Person.pmに、次のことを加えるだけです: our $VERSION = '1.1'; and then in Employee.pm could you can say そして、Employee.pm で、次のようにできます: use Employee 1.1; And it would make sure that you have at least that version number or higher available. This is not the same as loading in that exact version number. No mechanism currently exists for concurrent installation of multiple versions of a module. Lamentably. このことで、少なくともそのバージョン番号か、それより高いものが利用可能だと確かめます。 正確なバージョン番号でのロードなので、同じではありません。 現在のところ、共同に作用する複数のバージョンのモジュールのインストレーションのためには、 どんなメカニズムもありません。嘆かわしい。 =head1 ハッシュに代わるオブジェクトの表現(Alternate Object Representations) Nothing requires objects to be implemented as hash references. An object can be any sort of reference so long as its referent has been suitably blessed. That means scalar, array, and code references are also fair game. オブジェクトはハッシュリファレンスとして実装される必要はありません。 オブジェクトは、うまくblessされるリファレンスでありさえすれば、どんな種類のリファレンスでも可能です。 このことは、スカラーリファレンスでも、配列リファレンスでも、 コードのリファレンスでも、格好の的となるということです。 A scalar would work if the object has only one datum to hold. An array would work for most cases, but makes inheritance a bit dodgy because you have to invent new indices for the derived classes. スカラーは、オブジェクトがたった一つの値しか持たないなら、うまくいきます。 配列は、ほとんどのケースで、うまくいきます。ですが、継承を少々危うくします。 派生クラスのために、新しい索引を作り上げなければならないからです。 =head2 オブジェクトとして配列を If the user of your class honors the contract and sticks to the advertised interface, then you can change its underlying interface if you feel like it. Here's another implementation that conforms to the same interface specification. This time we'll use an array reference instead of a hash reference to represent the object. クラスを使う人が、契約を支持し、公示されたインターフェースに我慢するなら、 その基礎を成すインターフェースを、そうしたければ変えることが出来ます。 同じインターフェースの仕様に合う、他の実装です。 さて、オブジェクトを表現するのに、ハッシュリファレンスの代わりに、 配列リファレンスを使いましょう。 package Person; use strict; my($NAME, $AGE, $PEERS) = ( 0 .. 2 ); ############################################ ## オブジェクトコンストラクタ (配列版) ## ############################################ sub new { my $self = []; $self->[$NAME] = undef; # this is unnecessary $self->[$AGE] = undef; # as is this $self->[$PEERS] = []; # but this isn't, really bless($self); return $self; } sub name { my $self = shift; if (@_) { $self->[$NAME] = shift } return $self->[$NAME]; } sub age { my $self = shift; if (@_) { $self->[$AGE] = shift } return $self->[$AGE]; } sub peers { my $self = shift; if (@_) { @{ $self->[$PEERS] } = @_ } return @{ $self->[$PEERS] }; } 1; # require か、useが成功するために You might guess that the array access would be a lot faster than the hash access, but they're actually comparable. The array is a I bit faster, but not more than ten or fifteen percent, even when you replace the variables above like $AGE with literal numbers, like 1. A bigger difference between the two approaches can be found in memory use. A hash representation takes up more memory than an array representation because you have to allocate memory for the keys as well as for the values. However, it really isn't that bad, especially since as of version 5.004, memory is only allocated once for a given hash key, no matter how many hashes have that key. It's expected that sometime in the future, even these differences will fade into obscurity as more efficient underlying representations are devised. 配列アクセスはハッシュアクセスより、だいぶ速いと思うかもしれません。 ですが、この2つは、実際は、類似のものです。配列は、I<ちょっと>速い。 ですが、10か、50パーセントも速くはありません。たとえ、上の$AGEのような文字の変数を、 1のような数字に置き換えても、です。 二つのアプローチの大きな違いは、メモリの使用で見つけられます。 ハッシュでの表現は、配列での表現よりもメモリを多く消費します。 値と同じように、キーにも、メモリを割り当てなければならないからです。 しかし、そのことは、本当に、そんなに悪いことではありません。 特に、5.004からは、ハッシュにキーを与えるために、メモリは一度割り当てられるだけです。 いくつのハッシュがキーを持つのかは問題ではありません。 今後、この2つの違いは、より効率的な基礎となる表現が工夫されるにつれ、 あいまいに消滅していくだろうと、期待されています。 Still, the tiny edge in speed (and somewhat larger one in memory) is enough to make some programmers choose an array representation for simple classes. There's still a little problem with scalability, though, because later in life when you feel like creating subclasses, you'll find that hashes just work out better. まだ、スピード(と、メモリで、幾分大きくなるところ)で、ちょっと優れていることは、 プログラマに、単純なクラスのために配列表現を選ばせるのに十分です。 やはり、拡張性にちょっとした問題があります。後年、サブクラスを作ろうとと思ったときに、 ハッシュがちょうどうまく働くことがわかるでしょうから。 =head2 オブジェクトとしてクロージャを Using a code reference to represent an object offers some fascinating possibilities. We can create a new anonymous function (closure) who alone in all the world can see the object's data. This is because we put the data into an anonymous hash that's lexically visible only to the closure we create, bless, and return as the object. This object's methods turn around and call the closure as a regular subroutine call, passing it the field we want to affect. (Yes, the double-function call is slow, but if you wanted fast, you wouldn't be using objects at all, eh? :-) オブジェクトを表現するのに、コードリファレンスを使うことは、魅力ある将来性を 与えます。世界中で唯一人しか、オブジェクトのデータを見ることが出来ない、 新しい匿名の(クロージャ)関数を作ることが出来ます。 というのは、データをレキシカルにしか見えない無名ハッシュに置くからです。 つまり、クロージャを作り、blessし、オブジェクトとして返すからです。 このオブジェクトメソッドは、一変して、普通のサブルーチン呼出としてクロージャを呼び、 影響を与えたいフィールドに、それを渡します。 (はい、二重の関数呼び出しは、遅いです。ですが、もし、速さを求めるのなら、 オブジェクトをまったく使わなければいいんです。そうでしょ? :-) Use would be similar to before: 使いかたは、前と似ています; use Person; $him = Person->new(); $him->name("Jason"); $him->age(23); $him->peers( [ "Norbert", "Rhys", "Phineas" ] ); printf "%s is %d years old.\n", $him->name, $him->age; print "His peers are: ", join(", ", @{$him->peers}), "\n"; but the implementation would be radically, perhaps even sublimely different: ですが、実装は、根本的に、たぶん、圧倒的なやりかたで、違っています。 package Person; sub new { my $that = shift; my $class = ref($that) || $that; my $self = { NAME => undef, AGE => undef, PEERS => [], }; my $closure = sub { my $field = shift; if (@_) { $self->{$field} = shift } return $self->{$field}; }; bless($closure, $class); return $closure; } sub name { &{ $_[0] }("NAME", @_[ 1 .. $#_ ] ) } sub age { &{ $_[0] }("AGE", @_[ 1 .. $#_ ] ) } sub peers { &{ $_[0] }("PEERS", @_[ 1 .. $#_ ] ) } 1; Because this object is hidden behind a code reference, it's probably a bit mysterious to those whose background is more firmly rooted in standard procedural or object-based programming languages than in functional programming languages whence closures derive. The object created and returned by the new() method is itself not a data reference as we've seen before. It's an anonymous code reference that has within it access to a specific version (lexical binding and instantiation) of the object's data, which are stored in the private variable $self. Although this is the same function each time, it contains a different version of $self. (訳註:圧倒的に違うのは、)オブジェクトがコードリファレンスの背後に隠されているからです。 このことはちょっとミステリアスです。関数的なプログラム言語よりも、標準的な手続き型や、 オブジェクトベースのプログラミング言語の方が、そういった背景が、クロージャの由来するところから、 よりしっかりと定着しているからです(訳註:?)。 new() メソッドで作られて、返されたオブジェクトは、今まで見てきたような、 データのリファレンスではありません。オブジェクトは、匿名のコードリファレンスであり、 内部に、特定のバージョン(レキシカルにバインドしており、例示している(訳註:?)) の - プライベートな変数 $selfに蓄えられた - オブジェクトデータにアクセスするコードを持っています。 それは、毎回、同じ関数であるにもかかわらず、違ったバージョンの$self を含みます。 When a method like C<$him-Ename("Jason")> is called, its implicit zeroth argument is the invoking object--just as it is with all method calls. But in this case, it's our code reference (something like a function pointer in C++, but with deep binding of lexical variables). There's not a lot to be done with a code reference beyond calling it, so that's just what we do when we say C<&{$_[0]}>. This is just a regular function call, not a method call. The initial argument is the string "NAME", and any remaining arguments are whatever had been passed to the method itself. C<$him-Ename("Jason")>のようなメソッドが呼ばれると、 暗黙の0番目の引数がデフォルトとして呼び出されます -- 全てのメソッド呼出と一緒のように。 ですが、この場合では、その引数は先ほどのコードリファレンスです(C++でのポインタ関数のような何か、 ですが、レキシカルな変数に深くバインドされています)。 コードリファレンスを呼ぶこと以上に、コードリファレンスですることは多くはありません。 つまり、このときするのは、C<&{$_[0]}>とすることだけです。 これは、単なる普通の関数呼び出しであり、メソッド呼び出しではありません。 最初の引数は、文字列"NAME"であり、残りの引数は、メソッドに渡されているもの全てです。 Once we're executing inside the closure that had been created in new(), the $self hash reference suddenly becomes visible. The closure grabs its first argument ("NAME" in this case because that's what the name() method passed it), and uses that string to subscript into the private hash hidden in its unique version of $self. new() で作られたクロージャの内側で実行されると、$self ハッシュリファレンスは突然に見えるようになります。 クロージャは、その最初の引数(このケースでは、'NAME'です。name()メソッドがそれを渡したので)をつかんで、 その文字を、ユニークなのバージョンの$selfのプライベートで隠されたハッシュへの添字に使います。 Nothing under the sun will allow anyone outside the executing method to be able to get at this hidden data. Well, nearly nothing. You I single step through the program using the debugger and find out the pieces while you're in the method, but everyone else is out of luck. この世で、誰も、実行されているメソッドの外側にいるものには、 この隠されたデータに近付けることを許されていません。たぶん、ほとんどない。 デバッガを使っているプログラムを通すステップを選び、そのメソッドにいる間、 そのかけらを見つけることがI<できます>。ですが、他の全ての人には、運がありません。 There, if that doesn't excite the Scheme folks, then I just don't know what will. Translation of this technique into C++, Java, or any other braindead-static language is left as a futile exercise for aficionados of those camps. もし、このことがスキームなみなさんを興奮させなければ、何が興奮させるのかわかりません。 このテクニックの、C++や、Javaや、他の脳死状態の静的な言語への翻訳が、 このキャンプの熱狂的なファンのくだらない課題としては、残っていますが。 You could even add a bit of nosiness via the caller() function and make the closure refuse to operate unless called via its own package. This would no doubt satisfy certain fastidious concerns of programming police and related puritans. caller()関数で、ちょっとした詮索を加えることが出来ますし、 クロージャがそれ自身のパッケージを呼ばない限り、動作を拒否させることも出来ます。 このことは、まちがいなく、プログラミングポリスと、その親類の厳格な人の、 ある種の潔癖な関心事を満足させるでしょう。 If you were wondering when Hubris, the third principle virtue of a programmer, would come into play, here you have it. (More seriously, Hubris is just the pride in craftsmanship that comes from having written a sound bit of well-designed code.) もしも、いつ、傲慢- プログラマの三大美徳 - が開始するのかを疑問に思っていたなら、ここに、傲慢があります。 (もっとまじめにいうなら、傲慢は、ちょっとしたすばらしくよく設計されたコードを書くことから生じる腕前の、プライドです)。 =head1 AUTOLOAD: 代理メソッド Autoloading is a way to intercept calls to undefined methods. An autoload routine may choose to create a new function on the fly, either loaded from disk or perhaps just eval()ed right there. This define-on-the-fly strategy is why it's called autoloading. オートロードは、未定義のメソッドの呼び出しをインターセプトする方法です。 オートロードルーチンは、オン・ザ・フライに、新しい関数 - ディスクからロードされるか、たぶんevalされているもの - を作ることを選ぶかもしれません。このオン・ザ・フライに定義する作戦が、 オートローディング(訳註:自動装填?)と呼ばれる理由です。 But that's only one possible approach. Another one is to just have the autoloaded method itself directly provide the requested service. When used in this way, you may think of autoloaded methods as "proxy" methods. ですが、これはたった一つの可能なアプローチです。 他のアプローチは、オートロードされたメソッドそれ自身に、直接、要求されたサービスを提供させることです。 この方法を使ったとき、オートロードされたメソッドを"代理"メソッドのように、考えるかもしれません。 When Perl tries to call an undefined function in a particular package and that function is not defined, it looks for a function in that same package called AUTOLOAD. If one exists, it's called with the same arguments as the original function would have had. The fully-qualified name of the function is stored in that package's global variable $AUTOLOAD. Once called, the function can do anything it would like, including defining a new function by the right name, and then doing a really fancy kind of C right to it, erasing itself from the call stack. Perlが特定のパッケージの未定義の関数を呼ぼうとし、その関数が定義されていない場合、 同じパッケージにあるAUTOLOADと呼ばれる関数を探します。 もし、AUTOLOADがあれば、元の関数が持っていたのと同じ引数で、それが呼ばれます。 その関数の完全な正規の名前(訳註:パッケージ名で修飾された関数名)は、 パッケージのグローバル変数$AUTOLOADに蓄えられます。 いったん呼ばれると、関数は、好きなように何かをすることが出来ます。 適当名前で、新しい関数を定義すること、実際に装飾的な一種の、Cを、それに対して正しく行うこと、 コールスタックからそれ自身を消すことを、含みます(訳註:謎)。 What does this have to do with objects? After all, we keep talking about functions, not methods. Well, since a method is just a function with an extra argument and some fancier semantics about where it's found, we can use autoloading for methods, too. Perl doesn't start looking for an AUTOLOAD method until it has exhausted the recursive hunt up through @ISA, though. Some programmers have even been known to define a UNIVERSAL::AUTOLOAD method to trap unresolved method calls to any kind of object. これはオブジェクトと何が関係しますか? 結局、 関数に付いて話続けているのであって、メソッドについてではありません。 たぶん、メソッドは、単に特別な引数と、それが見つけれらる場所について、装飾的な記法を伴った ただの関数なので、オートローディングをメソッドとしても使うことが出来ます。 Perlは、@ISAを通したリカーシブな捜索に疲れ果てるまで、AUTOLOADメソッドを探し始めません。 どんな種類のオブジェクトに対する、未解決のメソッド呼び出しをトラップするために、 UNIVERSAL::AUTOLOADメソッドを定義する、プログラマがいることも知られています。 =head2 オートロードされるデータメソッド You probably began to get a little suspicious about the duplicated code way back earlier when we first showed you the Person class, and then later the Employee class. Each method used to access the hash fields looked virtually identical. This should have tickled that great programming virtue, Impatience, but for the time, we let Laziness win out, and so did nothing. Proxy methods can cure this. 最初にPersonクラスと、それから、Employeeクラスを見せた、はるか前に遡ったら、 二重化されたコードについて、おそらく、少し疑いを持ち始めるでしょう。 それぞれのメソッドは、仮想的にまったく同じに見えるハッシュのフィールドにアクセスしていました。 このことは、偉大なプログラミングの美徳である、短気をくすぐります。 ですが、このときに、不精を勝たせて、なにもしません。代理メソッドが、これを癒せます。 Instead of writing a new function every time we want a new data field, we'll use the autoload mechanism to generate (actually, mimic) methods on the fly. To verify that we're accessing a valid member, we will check against an C<_permitted> (pronounced "under-permitted") field, which is a reference to a file-scoped lexical (like a C file static) hash of permitted fields in this record called %fields. Why the underscore? For the same reason as the _CENSUS field we once used: as a marker that means "for internal use only". 新しいデータフィールドをが欲しいと思うたびに新しい関数を毎回書く代わりに、 オートロードのメカニズムを使って、(実際に、偽の)メソッドをオン・ザ・フライに生み出します。 妥当なメンバにアクセスしていることを証明するために、 C<_permitted>("under-permitted"と発音します)フィールドでチェックします。 このフィールドは、%fieldと呼ばれるレコードの中の許されたフィールドの、 ファイルスコープのレキシカルな(Cファイルstaticのような)ハッシュリファレンスです。 なぜ、アンダースコアがあるのか? かつて使った、_CENSUSフィールドと同じ理由のためです: "内部的に使うためだけ"を意味するマークです。 Here's what the module initialization code and class constructor will look like when taking this approach: ここにある、モジュールの初期化コードとクラスのコンストラクタは、 このアプローチを取る場合に見るようなものです: package Person; use Carp; our $AUTOLOAD; # it's a package global my %fields = ( name => undef, age => undef, peers => undef, ); sub new { my $that = shift; my $class = ref($that) || $that; my $self = { _permitted => \%fields, %fields, }; bless $self, $class; return $self; } If we wanted our record to have default values, we could fill those in where current we have C in the %fields hash. もし、レコードに、デフォルトの値を持たせたいなら、 現在の、%fieldハッシュにCのあるところに、それらを埋めることが出来ます。 Notice how we saved a reference to our class data on the object itself? Remember that it's important to access class data through the object itself instead of having any method reference %fields directly, or else you won't have a decent inheritance. オブジェクト自身に、クラスデータのリファレンスを保存させたやりかたに気づいたでしょうか? 直接に%fields を参照するメソッドを持つか、そのほか、礼儀正しい継承を持たない代わりに、 オブジェクトを通してクラスデータにアクセスすることが重要であることを思いだしてください。 The real magic, though, is going to reside in our proxy method, which will handle all calls to undefined methods for objects of class Person (or subclasses of Person). It has to be called AUTOLOAD. Again, it's all caps because it's called for us implicitly by Perl itself, not by a user directly. けれども、本当の魔法は、代理メソッドにあります。代理メソッドは、Person クラス(また、Personのサブクラス) のオブジェクトに対する未定義のメソッドの全ての呼び出しを取り扱います。 AUTOLOADと呼ばれなければなりません。再び、これは全て大文字になります。 ユーザが直接呼ぶのではなく、Perl自身によって、暗に呼ばれるからです。 sub AUTOLOAD { my $self = shift; my $type = ref($self) or croak "$self is not an object"; my $name = $AUTOLOAD; $name =~ s/.*://; # strip fully-qualified portion unless (exists $self->{_permitted}->{$name} ) { croak "Can't access `$name' field in class $type"; } if (@_) { return $self->{$name} = shift; } else { return $self->{$name}; } } Pretty nifty, eh? All we have to do to add new data fields is modify %fields. No new functions need be written. とっても素敵でしょ? 新しいデータフィールドを加えるときにしなければならないことは、 %fields を変更することだけです。新しい関数を書く必要はありません。 I could have avoided the C<_permitted> field entirely, but I wanted to demonstrate how to store a reference to class data on the object so you wouldn't have to access that class data directly from an object method. C<_parmitted>フィールドを、完全に、避けることが出来ましたが、 どのようにオブジェクトのクラスデータをリファレンスに蓄えるのかを実証したかったのです。 ですので、オブジェクトメソッドから、直接に、クラスデータにアクセスする必要はありません。 =head2 継承されるオートロードされるデータメソッド But what about inheritance? Can we define our Employee class similarly? Yes, so long as we're careful enough. しかし、継承ではどうなるのでしょう? Employeeクラスを同じように定義できるでしょうか? できます。十分に気をつける限りは。 Here's how to be careful: 気をつけ方です: package Employee; use Person; use strict; our @ISA = qw(Person); my %fields = ( id => undef, salary => undef, ); sub new { my $that = shift; my $class = ref($that) || $that; my $self = bless $that->SUPER::new(), $class; my($element); foreach $element (keys %fields) { $self->{_permitted}->{$element} = $fields{$element}; } @{$self}{keys %fields} = values %fields; return $self; } Once we've done this, we don't even need to have an AUTOLOAD function in the Employee package, because we'll grab Person's version of that via inheritance, and it will all work out just fine. これをしたら、Employeeパッケージに、AUTOLOAD関数を持つ必要はありません。 というのは、継承を通して、Personのバージョンを把握し、全て、うまく動くからです。 =head1 メタクラスなツールたち(Metaclassical Tools) Even though proxy methods can provide a more convenient approach to making more struct-like classes than tediously coding up data methods as functions, it still leaves a bit to be desired. For one thing, it means you have to handle bogus calls that you don't mean to trap via your proxy. It also means you have to be quite careful when dealing with inheritance, as detailed above. 代理メソッドが、データメソッドを関数としてくどくどコーディングするよりも、 より構造体ライクなクラスを作るのに、便利なアプローチを提供するといっても、 まだ、好ましいものが少し残されています。 第一には、代理メソッドを通してトラップさせるつもりのない、 いんちきの呼び出しを取り扱う必要があることを意味します。 上で詳細を述べたように、継承を扱う時に非常に慎重にならなければならないことも意味します Perl programmers have responded to this by creating several different class construction classes. These metaclasses are classes that create other classes. A couple worth looking at are Class::Struct and Alias. These and other related metaclasses can be found in the modules directory on CPAN. Perlプログラマは、さまざまなクラス生成クラスを作ることで、 これに対応しています。これらのメタクラスは他のクラスを作るクラスです。 見るべき組は、Class::Struct と、Aliasです。 これらと、他の関連するメタクラスは、CPANのモジュールディレクトリで見つけられます。 =head2 Class::Struct One of the older ones is Class::Struct. In fact, its syntax and interface were sketched out long before perl5 even solidified into a real thing. What it does is provide you a way to "declare" a class as having objects whose fields are of a specific type. The function that does this is called, not surprisingly enough, struct(). Because structures or records are not base types in Perl, each time you want to create a class to provide a record-like data object, you yourself have to define a new() method, plus separate data-access methods for each of that record's fields. You'll quickly become bored with this process. The Class::Struct::struct() function alleviates this tedium. その古いものの一つは、Class::Structです。 実際、その構文とインターフェースは、 perl5が実際のものに固まるだいぶ前に、スケッチされました。Class::Structは、 特定の型のフィールドがあるようなオブジェクトを持つクラスを"宣言"する方法を提供します。 それが呼ばれる関数は、驚くようなものではなく、struct()です。 構造、またはレコードは、Perlでは、基本の型ではないので、 レコードライクなオブジェクトを提供するクラスを作るたびに、 new()メソッドと、それに加えて、別個に、レコードの各フィールドのために、 データアクセスメソッドを定義しなければなりません。 このプロセスに、すぐに飽きてしまうでしょう。 Class::Struct::struct関数はこの退屈なことを緩和します。 Here's a simple example of using it: これを使う簡単な例です: use Class::Struct qw(struct); use Jobbie; # user-defined; see below struct 'Fred' => { one => '$', many => '@', profession => Jobbie, # calls Jobbie->new() }; $ob = Fred->new; $ob->one("hmmmm"); $ob->many(0, "here"); $ob->many(1, "you"); $ob->many(2, "go"); print "Just set: ", $ob->many(2), "\n"; $ob->profession->salary(10_000); You can declare types in the struct to be basic Perl types, or user-defined types (classes). User types will be initialized by calling that class's new() method. structの中で、型を宣言でき、それは基本的なPerlの型になるか、 ユーザー定義の型(クラス)になります。 ユーザー型は、そのクラスのnew()メソッドを呼ぶことによって、初期化されるでしょう。 Here's a real-world example of using struct generation. Let's say you wanted to override Perl's idea of gethostbyname() and gethostbyaddr() so that they would return objects that acted like C structures. We don't care about high-falutin' OO gunk. All we want is for these objects to act like structs in the C sense. structの生成を使った実際の例があります。たとえば、gethostbyname()と、gethostbyaddr()を、 C構造体のような振る舞いをするオブジェクトを返すように、オーバライドしたいとしましょう。 high-falutin' OO gunk は、気にしません。やりたいことは、これらのオブジェクトがC感覚で、 構造体のような振る舞いをすることです。 use Socket; use Net::hostent; $h = gethostbyname("perl.com"); # object return printf "perl.com's real name is %s, address %s\n", $h->name, inet_ntoa($h->addr); Here's how to do this using the Class::Struct module. The crux is going to be this call: Class::Structモジュールを使ってこれをする方法です。 最重要ポイントは、この呼び出しです: struct 'Net::hostent' => [ # note bracket name => '$', aliases => '@', addrtype => '$', 'length' => '$', addr_list => '@', ]; Which creates object methods of those names and types. It even creates a new() method for us. この呼び出しは、上記の名前と型のオブジェクトメソッドを作ります。 new() メソッドさえも作ります。 We could also have implemented our object this way: 次の方法でも、オブジェクトを実装できましたが、しませんでした: struct 'Net::hostent' => { # note brace name => '$', aliases => '@', addrtype => '$', 'length' => '$', addr_list => '@', }; and then Class::Struct would have used an anonymous hash as the object type, instead of an anonymous array. The array is faster and smaller, but the hash works out better if you eventually want to do inheritance. Since for this struct-like object we aren't planning on inheritance, this time we'll opt for better speed and size over better flexibility. こうすると、Class::Struct は、オブジェクト型を、無名配列の代わりに、 無名ハッシュを使います。配列は、ハッシュより速く、小さいですが、 ハッシュは、継承をしたいときに、よく働きます。 この構造体ライクなオブジェクには、継承を考えていないので、 今回は、よりよいスピードと、サイズに余裕をもたせることにしました。 Here's the whole implementation: 実装は次のようになります: package Net::hostent; use strict; BEGIN { use Exporter (); our @EXPORT = qw(gethostbyname gethostbyaddr gethost); our @EXPORT_OK = qw( $h_name @h_aliases $h_addrtype $h_length @h_addr_list $h_addr ); our %EXPORT_TAGS = ( FIELDS => [ @EXPORT_OK, @EXPORT ] ); } our @EXPORT_OK; # Class::Struct は、@ISA を使うのを禁止します sub import { goto &Exporter::import } use Class::Struct qw(struct); struct 'Net::hostent' => [ name => '$', aliases => '@', addrtype => '$', 'length' => '$', addr_list => '@', ]; sub addr { shift->addr_list->[0] } sub populate (@) { return unless @_; my $hob = new(); # Class::Struct made this! $h_name = $hob->[0] = $_[0]; @h_aliases = @{ $hob->[1] } = split ' ', $_[1]; $h_addrtype = $hob->[2] = $_[2]; $h_length = $hob->[3] = $_[3]; $h_addr = $_[4]; @h_addr_list = @{ $hob->[4] } = @_[ (4 .. $#_) ]; return $hob; } sub gethostbyname ($) { populate(CORE::gethostbyname(shift)) } sub gethostbyaddr ($;$) { my ($addr, $addrtype); $addr = shift; require Socket unless @_; $addrtype = @_ ? shift : Socket::AF_INET(); populate(CORE::gethostbyaddr($addr, $addrtype)) } sub gethost($) { if ($_[0] =~ /^\d+(?:\.\d+(?:\.\d+(?:\.\d+)?)?)?$/) { require Socket; &gethostbyaddr(Socket::inet_aton(shift)); } else { &gethostbyname; } } 1; We've snuck in quite a fair bit of other concepts besides just dynamic class creation, like overriding core functions, import/export bits, function prototyping, short-cut function call via C<&whatever>, and function replacement with C. These all mostly make sense from the perspective of a traditional module, but as you can see, we can also use them in an object module. 動的なクラスの作成に加えて、コアな関数のオーバーライドや、 import/export の例や、関数のプロトタイピングや、C<&whatever>を通しての 関数のショートカット呼び出しや、Cでの 関数の置き換えなどの他のコンセプトの正しい具体例を忍び込ませています。 これらの全ては、大半が、伝統的なモジュールの観点から意味のあるものです。 ですが、お分かりのように、オブジェクトモジュールとして、それらを使うことも出来ます。 You can look at other object-based, struct-like overrides of core functions in the 5.004 release of Perl in File::stat, Net::hostent, Net::netent, Net::protoent, Net::servent, Time::gmtime, Time::localtime, User::grent, and User::pwent. These modules have a final component that's all lowercase, by convention reserved for compiler pragmas, because they affect the compilation and change a builtin function. They also have the type names that a C programmer would most expect. 他の、オブジェクトベースのものや、File::stat、 Net::hostent、Net::netent、 Net::protoent、 Net::servent、 Time::gmtime、 Time::localtime、User::grent User::pwent で、Perlの5.004リリースのコアな関数の構造体ライクなオーバーライドを見ることが出来ます。 これらのモジュールは、コンパイラのプログラムのためにとってある、慣例によって、 全て小文字の最終的な構成要素を持っています。 これらが、コンパイルに影響し、組み込み関数を変更するからです。 これらは、Cのプログラマがよく期待する型名を持っています。 =head2 変数としてのデータメンバ If you're used to C++ objects, then you're accustomed to being able to get at an object's data members as simple variables from within a method. The Alias module provides for this, as well as a good bit more, such as the possibility of private methods that the object can call but folks outside the class cannot. C++オブジェクトをよく使うなら、メソッド内からオブジェクトのデータメンバを 単純な変数のように得ることが出来るのになれているでしょう。 Aliasモジュールは、これを提供します。同時に、ちょっとだけよいのは、 オブジェクトは呼ぶことが出来るけれど、クラスの外側のみんなは呼ぶことの出来ない、 プライベートなメソッドのようなところです。 Here's an example of creating a Person using the Alias module. When you update these magical instance variables, you automatically update value fields in the hash. Convenient, eh? AliasモジュールをつかってPersonを作る例です。 これらの魔術的なインスタンス変数を更新すると、 自動的にハッシュの値のフィールドを更新します。便利でしょ? package Person; # 前と同じです... sub new { my $that = shift; my $class = ref($that) || $that; my $self = { NAME => undef, AGE => undef, PEERS => [], }; bless($self, $class); return $self; } use Alias qw(attr); our ($NAME, $AGE, $PEERS); sub name { my $self = attr shift; if (@_) { $NAME = shift; } return $NAME; } sub age { my $self = attr shift; if (@_) { $AGE = shift; } return $AGE; } sub peers { my $self = attr shift; if (@_) { @PEERS = @_; } return @PEERS; } sub exclaim { my $self = attr shift; return sprintf "Hi, I'm %s, age %d, working with %s", $NAME, $AGE, join(", ", @PEERS); } sub happy_birthday { my $self = attr shift; return ++$AGE; } The need for the C declaration is because what Alias does is play with package globals with the same name as the fields. To use globals while C is in effect, you have to predeclare them. These package variables are localized to the block enclosing the attr() call just as if you'd used a local() on them. However, that means that they're still considered global variables with temporary values, just as with any other local(). Cを宣言しなければならないのは、Aliasがしているのが、 フィールドと同じ名前のパッケージのグローバル変数をいじれるようにするからです。 要するに、Cをしながら、グローバル変数を使うために、 これらを、先に宣言しなければなりません。 これらのパッケージの変数は、ちょうど、それらに、 local()を使ったように、attr()呼び出しを囲んでいるブロックに ローカライズされています。しかし、このことは、 ちょうど、他のlocal()のように、まだ、 一時的な値で、グローバル変数をで考えていることを意味します。 It would be nice to combine Alias with something like Class::Struct or Class::MethodMaker. Alias と、CLass::Structや、Class::MethodMakerを 混ぜてい使うと良いでしょう。 =head1 注意書き =head2 オブジェクト専門用語 In the various OO literature, it seems that a lot of different words are used to describe only a few different concepts. If you're not already an object programmer, then you don't need to worry about all these fancy words. But if you are, then you might like to know how to get at the same concepts in Perl. さまざまなオブジェクト指向文献で、たくさんの違った言葉がほんの少ししか違わない概念を 表すのに使われているように思います。もし、あなたがまだオブジェクト指向プログラマではないなら、 これらの、気まぐれな言葉に悩むことはありません。 ですが、もし、すでに、オブジェクト指向プログラマなら、Perlで、同じコンセプトをどのように 表すのか知りたいでしょう。 For example, it's common to call an object an I of a class and to call those objects' methods I. Data fields peculiar to each object are often called I or I, and data fields common to all members of that class are I, I, or I. 例えば、オブジェクトをクラスのI<インスタンス>と呼ぶことや、それらインスタンスのオブジェクトメソッドを I<インスタンスメソッド>と呼ぶことは、一般的でしょう。 オブジェクトごとに特有のデータフィールドはよく、I<インスタンスデータ>とか、 I<オブジェクト属性>と呼ばれ、全てのクラスのメンバに共通のデータフィールドは I<クラスデータ>や、I<クラス属性>や、I<静的データメンバ>とよく呼ばれるでしょう。 Also, I, I, and I all describe the same notion, whereas I, I, and I describe the other related one. また、I<基底クラス>や、I<一般クラス>やI<スーパークラス>など全てが、 同じ考えで記述します。ですので、I<派生クラス>やI<特定クラス>や、 I<サブクラス>は、他の関連するものを記述します。 C++ programmers have I and I, but Perl only has I and I. Actually, Perl only has methods. Whether a method gets used as a class or object method is by usage only. You could accidentally call a class method (one expecting a string argument) on an object (one expecting a reference), or vice versa. C++プログラマには、I<静的メソッド>やI<仮想メソッド>がありますが、 Perl プログラマには、I<クラスメソッド>と、I<オブジェクトメソッド>しかありません。 メソッドが、クラス/オブジェクトメソッドとして使われるかどうかは、使いかたによるだけです。 うっかりと、オブジェクト(リファレンスを期待するもの)で クラスメソッド(文字列の引数を期待するもの)を呼ぶことも出来ますし、その逆も出来ます。 From the C++ perspective, all methods in Perl are virtual. This, by the way, is why they are never checked for function prototypes in the argument list as regular builtin and user-defined functions can be. C++の観点からは、Perlの全てのメソッドは、仮想的です。 ところで、このことは、メソッドが、普通の組み込み関数やユーザ定義関数が出来るような、 引数リストで関数のプロトタイプを、チェックされない理由です。 Because a class is itself something of an object, Perl's classes can be taken as describing both a "class as meta-object" (also called I) philosophy and the "class as type definition" (I behaviour, not I mechanism) idea. C++ supports the latter notion, but not the former. クラスは、それ自身、オブジェクトの何かですので、Perlのクラスは、"メタオブジェクトとしてのクラス" (または、I<オブジェクト工場>とも呼ばれます)哲学と、"型定義としてのクラス" (振る舞いをI<宣言>し、メカニズムをI<定義しない>)考えの両方を表すものとして見られます。 C++は、後者をサポートしますが、前者は、サポートしません。 =head1 SEE ALSO The following manpages will doubtless provide more background for this one: 以下のマニュアルページは、まちがいなく、 このマニュアルページに多くの背景を与えてくれます: L, L, L, L, L, and L. L is a kinder, gentler introduction to object-oriented programming. L は、よりやさしい、オブジェクト指向プログラミングのイントロダクションです。 L provides more detail on class data. クラスデータに関する詳細を提供します。 Some modules which might prove interesting are Class::Accessor, Class::Class, Class::Contract, Class::Data::Inheritable, Class::MethodMaker and Tie::SecureHash 以下のモジュールは関心をひくでしょう。Class::Accessor, Class::Class, Class::Contract, Class::Data::Inheritable, Class::MethodMaker and Tie::SecureHash =head1 著者および著作権 (原文まま) Copyright (c) 1997, 1998 Tom Christiansen All rights reserved. This documentation is free; you can redistribute it and/or modify it under the same terms as Perl itself. Irrespective of its distribution, all code examples in this file are hereby placed into the public domain. You are permitted and encouraged to use this code in your own programs for fun or for profit as you see fit. A simple comment in the code giving credit would be courteous but is not required. =head1 著作権 (原文まま) =head2 Acknowledgment Thanks to Larry Wall, Roderick Schertler, Gurusamy Sarathy, Dean Roehrich, Raphael Manfredi, Brent Halsey, Greg Bacon, Brad Appleton, and many others for their helpful comments.