=encoding euc-jp =head1 NAME =begin original perltoot - Tom's object-oriented tutorial for perl =end original perltoot - トムによる Perl オブジェクト指向チュートリアル =head1 DESCRIPTION =begin original 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? =end original オブジェクト指向プログラミングは、昨今のビッグセラーです。 マネージャーには、薄切りパン(訳註: 良い発明のこと)よりもむしろ オブジェクトを持ちたがる人もいます。 どうしてでしょうか? オブジェクトの、何がそんなに特別なんでしょうか? そもそも、オブジェクトとは一体 I<何でしょう>? =begin original 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. =end original オブジェクトは、きちんとした小さな使いやすい包みに包んで、複雑なふるまいを 遠くへやってしまう方法以外のなにものでもありません。 (専門家は、このことを抽象化と呼びます。) 本当に難しい問題を片付けようと、何週間もぼーっと過ごしている、 賢い人たちは、普通の人でも使える、これらの素敵なオブジェクトを作ります。 (専門家は、このことをソフトウェアの再利用と呼びます。) オブジェクトを使う人(たぶん、プログラマ)は、自分が欲しい小さな包みを いじることができますが、その包みを開けて、中身にちょっかいを 出そうとはしません。 ちょうど、ハードウェアの高価な部分のように、契約は次のようになっています; 「カバーをいじくれば、保証は無効になります。」 ですから、そんなことをしてはいけません。 =begin original 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. =end original オブジェクトの核心は、クラスです; これは守られた小さな私的な 名前空間であり、データと関数が詰まっています。 クラスはいくつかの問題領域を扱う関連したルーチンの集合です。 クラスをユーザ定義の型と考えることもできます。 Perl のパッケージの仕組みは、より伝統的なモジュールと同じように、 クラスモジュールにも使われます。 オブジェクトは、クラスの中に、「住んで」います; つまり、 オブジェクトがいくつかのパッケージに属していることを意味します。 =begin original 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. =end original たいてい、クラスは、それを使う人にいくつかの小さな包みを提供します。 それらの包みがオブジェクトです。 オブジェクトは、自分が属しているクラスを知っていて、どのように振る舞うかも 知っています。 クラスを使う人は、クラスに、何かをするように、例えば 「オブジェクトをちょうだい」のように、頼むか、 オブジェクトの 1 つに何かをするように頼むことができます。 クラスに何かをするように頼むことは、I<クラスメソッド> を呼ぶことです。 オブジェクトに何かをするように頼むことは、I<オブジェクトメソッド> を 呼ぶことです。 クラス(普通)または、オブジェクト(たまに)に、オブジェクトを返すように 頼むことは、単にメソッドの一種である I<コンストラクタ> を呼ぶことです。 =begin original 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 is 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. =end original それはそれとして、オブジェクトは Perl の他のデータ型とどのように 違うのでしょうか? I<実際には>、オブジェクトは…オブジェクトの基礎の型は何なのでしょうか? 最初の質問に答えるのは、簡単です。 オブジェクトは、一つの、たった一つのやり方において、Perl の他のデータ型とは 違っています。 オブジェクトをデリファレンスするのに、単純な配列やハッシュのように、 単なる文字列や数字の添字ではなく、名前の付けられたサブルーチンの呼び出しを 使います。 一言でいえば、I<メソッド> でデリファレンスします。 =begin original 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. =end original 二番目の答えは、次のようになります。 オブジェクトはリファレンスですが、ただのリファレンスではありません。 注意してください。 特別なクラス(パッケージ)に I<祝福(bless)されている> リファレンスを 持っているものです。 リファレンスの種類は? たぶん、その質問の答えは、あまり具体的にはなりません。 Perlでは、基礎となる固有のデータ型として、リファレンスならどんな種類の ものでも、クラス設計者の好きなように使うことが出来るからです。 リファレンスなら、スカラでも、配列でも、ハッシュでもかまいません。 コードのリファレンスすらありえます。 ですが、持ち前の柔軟性により、普通、オブジェクトはハッシュリファレンスです。 =head1 Creating a Class (クラスを作る) =begin original 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. =end original クラスを作る前に、クラスに何という名前を付けるかを決めなければなりません。 クラス(パッケージ)の名前は、普通のモジュールと同じように、クラスを納める ファイル名を左右します。 それから、そのクラス(パッケージ)は、一つか、それ以上の方法で、オブジェクトを 生成する方法を提供すべきです。 最後に、クラス(パッケージ)は、オブジェクトを使う人に、離れたところから 間接的にオブジェクトを操作することのできるメカニズムを提供すべきです。 =begin original For example, let's make a simple Person class module. It gets stored in the 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. =end original 例えば、単純な Person クラスモジュールを作ってみましょう。 このクラスモジュールは、Person.pm に保存されます。 もし、このクラスモジュールが、Happy::Person クラスと呼ばれるなら、 このクラスは、Happy/Person.pm ファイルに保存されます。 そして、そのパッケージは、ただの、Person ではなく、Happy::Person になります。 (Unix か、Plan 9 ではなく、Mac OS やVMS のような OS の動いている パーソナルコンピュータ上では、ディレクトリのセパレータは 違っているでしょうが、原則は同じです)。 ディレクトリ名のベースとなるモジュールとの間にどのような公式な関係も 想定してはいけません。 これは、単に、グループ分けを便利にしているだけで、継承や変数の アクセシビリティなど、その他諸々に、何の効果も与えません。 =begin original 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. =end original このモジュールに Exporter は使わないでおきましょう。 私たちは行儀が良いし、行儀が良いクラスモジュールはまったく何も export しないからです。 オブジェクトを作るためには、クラスに、I<コンストラクタメソッド> が必要です。 コンストラクタは、普通のデータ型ではなく、おろしたてのクラスのオブジェクトを 返します。 この魔法は bless() 関数によって扱われます。 bless() の唯一の目的は、リファレンスをオブジェクトとして使えるように することです。 銘記:オブジェクトであることは、実際には、メソッドが、そのオブジェクトを 背景にして、呼ばれるということ以上に何も意味しません。 =begin original 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. =end original コンストラクタは好きなように名付けても構いませんが、ほとんどの Perl プログラマはコンストラクタを、new() と呼ぶのを好むようです。 ですが、new() は予約語ではありませんし、クラスにはそういったものを供給する 義務もありません。 コンストラクタとして、クラスと同じ名前の関数を使うプログラマにがいることも 知られています。 =head2 Object Representation (オブジェクトの表現) =begin original 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. =end original Pascal のレコードや、C の構造体や、C++ のクラスを表すために、 Perl で使われている、もっとも一般的なメカニズムは、無名ハッシュです。 ハッシュには任意の数のデータ領域があり、自分でつけた任意の名前で、 それぞれにアクセスしやすいからです。 =begin original If you were just doing a simple struct-like emulation, you would likely go about it something like this: =end original 単純な構造体風なエミュレーションをするなら、次のようにすることができます: $rec = { name => "Jason", age => 23, peers => [ "Norbert", "Rhys", "Phineas"], }; =begin original If you felt like it, you could add a bit of visual distinction by up-casing the hash keys: =end original 違いをつけたいと感じたら、大文字のハッシュキーによって、 見た目に、ちょっとした違いを加えることができます: $rec = { NAME => "Jason", AGE => 23, PEERS => [ "Norbert", "Rhys", "Phineas"], }; =begin original 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? :-) =end original これで、C<< $rec->{NAME} >> で、"Jason" を見付けることができるようになり、 また、C<< @{ $rec->{PEERS} } >> で、"Norbert" と、"Rhys" と "Phineas" を 得ることができます。 (昨今、どれくらい多くの、23 才のプログラマが、Jason と 名付けられているか気にしたことがありますか? :-) =begin original 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. =end original これと同じモデルは複数のクラスでよく使われてますが、 とはいっても、クラスの外から、皆がオブジェクトにワルツを踊らせて、 そのデータメンバにずうずうしく直接にアクセスすることは、 プログラミングの礼儀正しさの頂点をよく考えたものではありません。 概して、オブジェクトは I<オブジェクトメソッド> を使ってアクセスする、 不可解なクッキーと考えるべきです。 見た目には、メソッドは、ブラケットや、ブレイスの代わりに、 関数名を使って、リファレンスをデリファレンスしているように見えます。 =head2 Class Interface (クラスのインターフェース) =begin original 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.) =end original 言語には、クラスのメソッドのための正式な総合のインターフェースを 提供しているものもありますが、Perl はそうではありません。 使う人がそれぞれのクラスのドキュメントを読むのを当てにしています。 定義されていないメソッドをオブジェクトで呼んだら、Perl は、文句を 言おうとはしませんが、プログラムは、実行中に例外をおこすでしょう。 同じように、引数に素数を期待するメソッドに、素数でない数字を引数にして 呼んだとしても、コンパイラがそのことを捕らえてくれることは期待できません。 (たぶん、あなたは、コンパイラにあなたの好むすべてを期待するでしょうが、 そんなことは起こりません。) =begin original 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: =end original Person クラスを使う人が、よく教育された、所定のインターフェースを 説明するドキュメントを読んでいる人だと想定しましょう。 Person クラスの使いかたがここにあります: use Person; $him = Person->new(); $him->name("Jason"); $him->age(23); $him->peers( "Norbert", "Rhys", "Phineas" ); =begin original push @All_Recs, $him; # save object in array for later =end original 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; =begin original 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. =end original 上のように、そのクラスを使う人は、オブジェクトにある特定の実装があるか、 他の実装があるかを知りません(少なくとも、その事実に注意を払うかは 無関係です)。 クラスとそのオブジェクトへのインターフェースは、専らメソッド経由です。 そして、クラスを使う人はみんな、メソッドをいじるべきです。 =head2 Constructors and Instance Methods (コンストラクタとインスタンスメソッド) =begin original 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. =end original まだ、I<誰か> は、オブジェクトに何があるかを知る必要があります。 そして、その誰かとは、クラスです。 クラスはプログラマが、オブジェクトにアクセスするのに使うメソッドを実装します。 ここに示すのは、標準的なオブジェクトのようにハッシュリファレンスを使う イディオムを使い、Person クラスに実装する方法です。 コンストラクタとして働く new() というクラスメソッドを作りましょう。 そして、3 つのオブジェクトメソッド、name() と、age() と、peers() を作り、 オブジェクトごとに、無名ハッシュにデータを隠すようにします。 package Person; use strict; =begin original ################################################## ## the object constructor (simplistic version) ## ################################################## sub new { my $self = {}; $self->{NAME} = undef; $self->{AGE} = undef; $self->{PEERS} = []; bless($self); # but see below return $self; } =end original ######################################################### ## オブジェクトのコンストラクタ (単純化したバージョン )## ######################################################### sub new { my $self = {}; $self->{NAME} = undef; $self->{AGE} = undef; $self->{PEERS} = []; bless($self); # 下を見て下さい return $self; } =begin original ############################################## ## methods to access per-object data ## ## ## ## With args, they set the value. Without ## ## any, they only retrieve it/them. ## ############################################## =end original ##################################################### ## オブジェクトごとのデータにアクセスするメソッド ## ## ## ## 引数があれば、値をセットする。引数がなければ ## ## 値を返す。 ## ##################################################### 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} }; } =begin original 1; # so the require or use succeeds =end original 1; # require か、use を成功させるために =begin original 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. =end original オブジェクトのデータにアクセスする3つのメソッド、name()、age()、peers() を、 作りました。 これらは、実質は、すべて似たようなものです。 引数つきで呼べば、しかるべきフィールドに、値をセットし、引数がなければ、 そのフィールドに保持されている値を返します。 ハッシュのキーの値を意味します。 =head2 Planning for the Future: Better Constructors (将来を考える: よりよいコンストラクタ) =begin original 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. =end original たとえ、この時点でその意味することを知らなくてよくても、いつの日か継承に 悩むことになるでしょう。 (お望みなら、今のところ継承を安全に無視し、後で、継承に悩むこともできます)。 継承が、全てスムーズにうまくいくことを保証するには、bless() に2つの引数を 渡さなければいけません。 2 番目の引数はクラスですが、リファレントを祝福(bless)するクラスです。 デフォルトでは、(訳註:2 番目の引数を省略すると)2 番目の引数として自分自身の クラスを想定します。 そのかわりに、(訳註:コンストラクタの第一引数に)渡されるクラスを使います。 こうすることで、コンストラクタは継承できるようになります。 sub new { my $class = shift; my $self = {}; $self->{NAME} = undef; $self->{AGE} = undef; $self->{PEERS} = []; bless ($self, $class); return $self; } =begin original 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. =end original これが、コンストラクタの全てです。 これらのメソッドは、オブジェクトに命をもたらし、きちんとした、小さくて、 不可解な束をユーザに返し、次のメソッドの呼出しに使われます。 =head2 Destructors (デストラクタ) =begin original 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. =end original 全ての話には、始まりがあり、終わりがあります。 オブジェクトの話の始まりには、コンストラクタがあり、オブジェクトが 存在しはじめる時には、明示的にコンストラクタが呼ばれます。 オブジェクトの話の終わりは、I<デストラクタ> ですが、このメソッドは、 オブジェクトがその命を無くすときに暗黙のうちに呼ばれます。 オブジェクトごとの後かたづけのコードがデストラクタにあり、デストラクタは、 (Perl では)DESTROY と呼ばれなければいけません。 =begin original 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. =end original コンストラクタは恣意的な名前であるのに、なぜ、デストラクタは 恣意的でないのでしょうか? その理由は、コンストラクタは、明示的に呼ばれますが、デストラクタは そうではないからです。 デストラクタの呼出しは、Perl のガベージコレクションシステム経由で、 自動的に起こります。 素早いですが、幾分、怠惰なリファレンスに基づいた、ガベージ コレクションシステムです。 呼ぶべきものが何かわかるように、Perl は、デストラクタが DESTROY と 名付けられることを要求します。 Perl はデストラクタを呼ぶ適切な時期を考えますが、現在のところいつ 呼ばれるかははっきり定義されていません。 このために、デストラクタは、それがいつ呼ばれるかを当てに すべきではありません。 =begin original 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. =end original なぜ、DESTORY はすべて大文字なのでしょう? Perl は、ときどき、慣例で全て大文字の関数名を使います。 この関数は、なんらかの方法で Perl によって自動的に呼ばれるかも しれないことを示します。 DESTROY の他に、暗黙のうちに呼ばれるものには、BEGIN や END や AUTOLOAD、 加えて、L に書かれている、tie されたオブジェクトに使われる全ての メソッドなどが含まれます。 =begin original 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. =end original 本当によいオブジェクト指向プログラム言語では、ユーザは、デストラクタが 呼ばれるときを気にしません。 起こるであろうときに、ただ、起きるのです。 どんなガベージコレクションもまったくない、低レベルの言語では、 適切な時期にデストラクタが呼び出されることをまったく当てに出来ません。 そのため、プログラマは、明示的にデストラクタを呼び、メモリや状態の 後かたづけをする必要があります。 C++ とは違って、オブジェクトのデストラクタは、ほとんど、Perl では 必要とされていません。 そして、デストラクタがあるときでさえ、明示的呼び出しは、ありません。 Person クラスの場合は、デストラクタを必要としません。 というのは、メモリの割り当て解除のような単純な問題は、 Perl が面倒をみるからです。 =begin original The only situation where Perl's reference-based GC won't work is when there's a circularity in the data structure, such as: =end original Perl のリファレンスに基づく、ガベージコレクションが働かない唯一の状況は、 データ構造に循環性があるときです。 次のようなものです: $this->{WHATEVER} = $this; =begin original 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.) =end original プログラムがメモリリークをしないことを期待するなら、この場合、自己参照を 手動で削除しなければなりません。 明らかに、エラーを起こしやすい状態で、これは、ただ今できるベストなことです。 にもかかわらず、プログラムが終わるときに、そのオブジェクトのデストラクタが 全て正式に呼ばれるので、安全が保証されます。 そのため、次のことが保証されます。 プログラムが終了していない唯一の場合をのぞいて、オブジェクトが、 I<最終的に>適切に、破壊されます。 (他のアプリケーションに埋め込んで Perl を走らせているなら、この徹底した ガベージコレクションの通過は、普段より少々頻繁に - スレッドが終了する度に - 起こります)。 =head2 Other Object Methods (他のオブジェクトメソッド) =begin original 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. =end original 今までに話しているメソッドは、コンストラクタか、他は、単純な "データメソッド"であり、 オブジェクトに蓄えられているデータへのインターフェースです。 これらのデータは、C++ での、オブジェクトのデータメンバに少し似ています。 見知らぬ人がデータとして、オブジェクトのデータメンバに アクセスできないことを期待します。 その代わりに、オブジェクトのデータメンバにデータメソッド経由で、 間接的にアクセスすべきです。 このことは Perl で、重要なルールです。 Perl では、オブジェクトのデータへのアクセスは、メソッドを通して I<のみ> なされるべきです。 =begin original 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. =end original Perl は、誰がどのメソッドを使えるかの制限を押しつけません。 パブリック と プライベート の違いは慣例によるもので、構文にはよりません。 (たぶん、L に、下の方で記述する Alias モジュールを 使わない場合は)。 メソッドの名前が一つか、2 つののアンダースコアで始まっているか、 終わっているものを見ることがあるでしょう。 このマークは、慣例的に次のことを示します。 そのメソッドがそのクラスだけ、および、密接なその知合い、つまりサブクラスの プライベートなものであることを示します。 ですが、この区別は Perl 自身によって強制されてはいません。 そう振る舞うことは、プログラマ次第です。 =begin original 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. =end original メソッドを単純なデータにアクセスするものだけに限定する理由はありません。 メソッドは、まったく、なんでもできます。 キーポイントは、メソッドは、オブジェクトかクラスを背景に 呼び出されるということです。 たとえば、一つの特別なフィールドから値を持ってきたりセットしたりする 以上のことをするオブジェクトメソッドを示しましょう。 sub exclaim { my $self = shift; return sprintf "Hi, I'm %s, age %d, working with %s", $self->{NAME}, $self->{AGE}, join(", ", @{$self->{PEERS}}); } =begin original Or maybe even one like this: =end original または、次のようなもの: sub happy_birthday { my $self = shift; return ++$self->{AGE}; } =begin original Some might argue that one should go at these this way: =end original 次のような方法でやると言う人もいるでしょう: 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 ); } =begin original 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. =end original ですが、これらのメソッドはクラス自身ですべて実行できるので、このことは 重要ではないかもしれないません。 トレードオフがあります。 直接なハッシュのアクセスはそうでない場合より速く(実際のところ、 およそ桁違いに速く)、文字列に手を加えたい時には、より便利です。 ですが、メソッド(外部のインターフェース)を使うと、内部的に、 クラスを使う人だけでなく、クラスの作者自身が、データ表現に変更を 加えることの盾にもなります。 =head1 Class Data (クラスデータ) =begin original 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? =end original "クラスデータ" - クラスのそれぞれのオブジェクトに共通のデータアイテム - とは なんでしょう? 何のためにクラスデータが欲しいでしょう? たぶん、Person クラスでは、生きている人々の総数を追っておきたいでしょう。 =begin original 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. =end original $Person::Census と呼ばれるグローバル変数でそういうことが I<できます>。 ですが、そのようにする唯一の理由は、人々が直接にクラスデータを 得られるようにしたい場合です。 $Person::Census と言うだけで、それをいじることが出来ます。 あなたの考えでは、そういったことは構わないのかもしれません。 ひょっとすると、変数が持ち出されることさえ、望んでいるかもしれません。 持ち出されるのであれば、(パッケージの)グローバル変数でなければなりません。 これがオブジェクト指向的なモジュールでなく、伝統的なモジュールであれば、 そうすればいいでしょう。 =begin original 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. =end original クラス変数をパッケージのグローバル変数にするやり方は、ほとんどの伝統的な モジュールで、期待されています。 ですが、このやり方は、一般的に、ほとんどのオブジェクト指向のモジュールでは、 むしろ下手なものと考えられています。 オブジェクト指向のモジュールでは、(訳註: データを)保護をするベールを設けて、 実装とインターフェースを分離します。 ですから、オブジェクトデータにアクセスするオブジェクトメソッドを 提供するのと同じように、クラスデータにアクセスするクラスメソッドを提供します。 =begin original 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. =end original それで、まだ、$Census をパッケージのグローバル変数とし続けることが、 I<できますし>、そして、他人がモジュールの契約を支持し、そのために、 その実装をいじくり回さないと信頼することが I<できます>。 かなりトリッキーに、Lに記述されているように、$Census を、 tie されたオブジェクトにすることもできます。 =begin original 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: =end original ですが、たいていは、クラスデータをファイルスコープのレキシカル変数に したいと思います。 そうするためには、ファイルの上の方で、単純に次のものを置けばいいのです: my $Census = 0; =begin original 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. =end original my() のスコープは、ふつう宣言されたブロックが終わったとき(この場合では、 全てのファイルが必要とされ、使われているとき)が期限ですが、Perl の レキシカル変数の深い束縛は、そのスコープ内で宣言された関数に アクセスできる間は、変数が割り当て解除されないことを保証します。 このことは、local() にて、一時的な値を与えられたグローバル変数では、 働きません。 =begin original 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: =end original $Census をパッケージのグローバル変数のままにするか、代わりに、 ファイルスコープのレキシカル変数にするかどうかに関わりなく、 Person::new() コンストラクタに、次のような変更をするべきです。 sub new { my $class = shift; my $self = {}; $Census++; $self->{NAME} = undef; $self->{AGE} = undef; $self->{PEERS} = []; bless ($self, $class); return $self; } sub population { return $Census; } =begin original 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: =end original こうしたことで、もちろん、Person が壊れたときに、$Census を減らすために、 デストラクタが必要になります。 次のようにします: sub DESTROY { --$Census } =begin original Notice how there's no memory to deallocate in the destructor? That's something that Perl takes care of for you all by itself. =end original デストラクタ内で、割り当て解除するためのメモリがないことに、どのようにして 気づくのでしょう? そのことは、Perl 自身が面倒をみます。 =begin original Alternatively, you could use the Class::Data::Inheritable module from CPAN. =end original 代わりに、CPANから、Class::Data::Inheritable モジュールを使うことも出来ます。 =head2 Accessing Class Data (クラスデータにアクセスする) =begin original 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. =end original クラスデータを絶えず取り扱うやり方は、本当によくないことがわかります。 十分に拡張的なルールは、I<オブジェクトメソッドから、直接にクラスデータを 参照しない> ことです。 そうでなければ、拡張的な、継承できるクラスは作らないことです。 オブジェクトは、全てのオペレーションのために、ランデブーポイントに いなければなりません。 特に、とりわけオブジェクトメソッドからは。グローバル変数(クラスデータ)は、 ある意味で、派生クラスの中で、「間違った」パッケージにあります。 Perl では、メソッドはメソッドが定義されたクラス内のコンテキストで 実行するのであり、メソッドが動かされたオブジェクトの コンテキストでは I<ありません>。 そのために、名前空間 - メソッド内で、目に見えるパッケージの グローバル変数の - は、継承と無関係です。 =begin original 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. =end original その名前空間を得られるでしょうか? たぶん、無理です。 よし、たとえば、他のクラスが、上で定義されているような(訳註:Person クラスの) DESTORY メソッドを、(たぶん継承されて)「借りた」としましょう。 これらの他のクラスのオブジェクトが破壊されたら、オリジナルの $Census 変数は 変化させられます。 新しいクラスのパッケージの名前空間の $Census ではありません。 ひょっとしたら、このことは、あなたの望むものかもしれませんが、十中八九 違うでしょう。 =begin original 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.) =end original これを修正する方法があります。 ハッシュのキー "_CENSUS" で、アクセスされる値のデータにリファレンスを 蓄えます。 なぜアンダースコアをつけるかって? たぶん、たいてい、最初のアンダースコアは、いつも C プログラマに不思議な感覚を 伝えるからです。 このフィールドが、特殊であり、NAME や、AGE や PEERS と同じようなパブリックな データメンバではないということを思い出させる、単なる、記憶を助ける工夫です。 (このコードは、strict プラグマをつけて、開発しているので、 perl 5.004 以前なら、フィールド名をクォートしないといけないでしょう) sub new { my $class = shift; 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 Debugging Methods (デバッグメソッド) =begin original 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. =end original クラスにデバッグのメカニズムがあるのは、一般的です。 たとえば、オブジェクトが作られるか、破壊される時に、(訳註: デバッグ情報を) 見たいでしょう。 そうするためには、デバッグの値をファイルスコープのレキシカル変数に加えます。 このために、警告と致命的なメッセージを発する標準の Carp モジュールを 呼びましょう。 この方法により、自分自身のメーッセージの代わりに caller のファイル名と 行数と一緒に出ます; もし、自分自身の観点から、警告や致命的なメッセージが欲しいのなら、 croak() の代わりに、ただ、die() と warn() を、直接に使いましょう。 use Carp; my $Debugging = 0; =begin original Now add a new class method to access the variable. =end original さて、新しいクラスメソッドに、変数のアクセスを加えましょう。 sub debug { my $class = shift; if (ref $class) { confess "Class method called as object method" } unless (@_ == 1) { confess "usage: CLASSNAME->debug(level)" } $Debugging = shift; } =begin original Now fix up DESTROY to murmur a bit as the moribund object expires: =end original さて、DESTROY に手を入れて、消滅しかけているオブジェクトが失効する時に ちょっと文句を言うようにしましょう: sub DESTROY { my $self = shift; if ($Debugging) { carp "Destroying $self " . $self->name } -- ${ $self->{"_CENSUS"} }; } =begin original One could conceivably make a per-object debug state. That way you could call both of these: =end original ひょっとしたら、オブジェクトごとに、デバッグ状態を持ちたいかも知れません。 両方ともできるを方法があります: Person->debug(1); # entire class $him->debug(1); # just this object =begin original 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: =end original こうするためには、デバッグメソッドは、「二頂の」メソッドで なければなりません。 クラス 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"} }; } =begin original 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. =end original (Employee と呼ばれる)派生クラスが、Person 基底クラスからメソッドを 継承していると、何が起きるでしょうか? C<< Employee->debug() >> は、クラスメソッドとして呼ばれた場合、 $Employee::Debugging ではなく、$Person::Debugging を操作します。 =head2 Class Destructors (クラスのデストラクタ) =begin original 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, =end original オブジェクトのデストラクタは、それぞれの別個のオブジェクトごとの死を 取り扱います。 しかし、クラス全体のシャットダウン - これは現在のところプログラムが 終了した時に起こる - ちょっとした掃除が欲しいときもあります。 そのような I<クラスのデストラクタ> を作るために、 そのクラスパッケージの中に、END と名付けられる関数を作ります。 END の働きは、伝統的なモジュールの END 関数とちょうど似ています。 プログラムが実行されないか、捕らえられないシグナルで死んで、 プログラムが終了したときにいつでも呼ばれます。 例えば、 sub END { if ($Debugging) { print "All persons are going away now.\n"; } } =begin original 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 original プログラムが終了しとき、全てのクラスデストラクタ(END 関数)は、 クラスがロードされたのと反対の順番(LIFO の順番)で呼ばれます。 =head2 Documenting the Interface (インターフェースをドキュメントにする) =begin original 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: =end original そして、ドキュメントがあります: 今まで、この 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.... =begin original 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. =end original インターフェース対実装の問題があります。 モジュールを開いて、インターフェースの契約の後ろにある、安全に鍵を かけられた、全てのプライベートなほのかに輝く小さなものを、 いじくりまわすようなプログラマには、保証が無効になります; 彼らの運命を気に病むべきではありません。 =head1 Aggregation (集約(Aggregation)) =begin original 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. =end original 後になって、よりよい名前を実装するために、クラスを変えたくなったとしましょう。 たぶん、ファーストネーム(その人の宗教にかかわりなく、クリスチャンネームと 呼ばれる)とファミリーネーム(名字と呼ばれる)の両方と、それに加えて、 ニックネームと称号もサポートしたくなったとします。 もし、Person クラスを使う人が、このドキュメントに書かれたインターフェースを 通して、適切にアクセスしていれば、簡単にその下にある実装を変更出来ます。 もし、そうでなければ、Person クラスを使う人は損をします。 契約を破り、保証を失効したむくいです。 =begin original 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: =end original 次のようにして、他のクラスを作ります。 このクラスは、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; =begin original Ok. To do this, we'll change Person::new() so that it supports a full name field this way: =end original よし。 こうするために、Person::new() をフルネームのフィールドをサポートするように、 次のように変えます: sub new { my $class = shift; 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}; } =begin original Then to support old code, define Person::name() this way: =end original それから、古いコードをサポートするために、Person::name() を次のように 定義します: sub name { my $self = shift; return $self->{FULLNAME}->nickname(@_) || $self->{FULLNAME}->christian(@_); } =begin original 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: =end original これが Fullname クラスです。 データフィールドを持つのにハッシュリファレンスを使ったのと同じテクニックを 使い、データフィールドにアクセスするのに適切な名前でメソッドを使います: package Fullname; use strict; sub new { my $class = shift; 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; =begin original Finally, here's the test program: =end original 最後に、テストプログラムです: #!/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->as_string; 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 Inheritance (継承) =begin original 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.) =end original オブジェクト指向プログラミングのシステムは、全て、継承の考えをサポートします。 継承は、一つのクラスが他のクラスの上におんぶすることを意味します。 ですから、同じコードをくり返し、くり返し、書かなくて済みます。 つまり、ソフトウェアの再利用です。 そして、それゆえ、不精 - プログラマの重要な美徳 - に関連します。 (伝統的なモジュールの import/export メカニズムもまた、コードの再利用の形です。 ですが、オブジェクトモジュールに見られる、本当の継承よりも単純なものです) =begin original 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. =end original 継承の文法は、時に、言語の核に組み込まれていることがあれば、 そうでないときもあります。 Perlは、一つのクラス(や、複数のクラス)から、継承するのに特別な文法は ありません。 その代わりに、全て厳密に意味論にあります。 それぞれのパッケージには、@ISA と呼ばれる変数があり、@ISA は、 (メソッド)継承を治めるものです。 もし、オブジェクトかクラスで、メソッドを呼ぼうとして、そのメソッドが、 そのオブジェクトのパッケージには見付からないと、Perl は、見付からない メソッドを検索するさいに、@ISA を見て、他のパッケージを探しに行きます。 =begin original 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. =end original 特別なパッケージ毎の、Exporter で認識される変数 (@EXPORT, @EXPORT_OK, @EXPORT_FAIL, %EXPORT_TAGS, $VERSION) のように、 @ISA 配列は、パッケージスコープのグローバル変数で I<なければならず>、 my() で作られるファイルスコープのレキシカル変数であっては I<いけません>。 ほとんどのクラスで、@ISA 配列には一つのものしかありません。 このことは、「単一継承」("single inheritance")と呼ばれるものです。 省略して、SI とも呼ばれます。 =begin original Consider this class: =end original このクラスについて、考えてみましょう: package Employee; use Person; @ISA = ("Person"); 1; =begin original 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. =end original 多くないでしょ? 今のところ、この Employee クラスがするのは、他のクラスをロードすることと、 必要なら、その、他のクラスからメソッドを継承することを始めることだけです。 Employee クラスには、それ自身のメソッドを与えてはいません。 ですが、Employee クラスに、ちょうど Person クラスのような振る舞いを 当てにします。 =begin original 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: =end original このような空のクラスを作ることは、「空のサブクラステスト」と呼ばれます。 これは、基底クラスから継承する以外には、なにもしない派生クラスを 作ることです。 オリジナルの基底クラスは、適切に設計されていれば、 新しい派生クラスは、古いものの差し込み式の置換として、使われます。 このことが意味するのは、次のようにプログラムを書けるということです: use Employee; my $empl = Employee->new(); $empl->name("Jason"); $empl->age(23); printf "%s is age %d.\n", $empl->name, $empl->age; =begin original 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. =end original 適切な設計によって、そうできます。 適切な設計とは、常に bless() に、2 つの引数を与え、グローバルなデータに 直接アクセスするのを避け、何も export しない設計のことです。 上の方で定義している Person::new() 関数を見返したら、そうするように 注意しています。 コンストラクタで使われるパッケージデータが少しありますが、 パッケージデータへのリファレンスが、オブジェクト自身に蓄えられており、 他の全てのメソッドはそのリファレンスを通してパッケージデータに アクセスします; それで、よしとすべきです。 =begin original 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. =end original Person::new() 関数で、意図したこと -- 実際にはメソッドではないですか? たぶん、原則的には、メソッドです。 メソッドは、ちょうど、その最初の引数に、クラスの名前(パッケージ)か、 オブジェクト(bless されたリファレンス)を期待する関数です。 Person::new()は、結局、C<< Person->new() >> メソッドと C<< Employee->new() >> メソッドの両方が呼んでいる関数です。 メソッド呼び出しが関数呼び出しによく似ていながら、本当は、まったく 同じではなく、この 2 つを同じものとして扱うなら、すぐに壊れたプラグラムしか 残されないことを理解してください。 第一に、現実に、基礎となっている呼び出しの慣例が違っています: メソッド呼び出しは、特別な引数を得ます。 第二に、関数呼び出しは継承をしませんが、メソッド呼び出しは継承をします。 =begin original Method Call Resulting Function Call ----------- ------------------------ Person->new() Person::new("Person") Employee->new() Person::new("Employee") =end original メソッド呼出 結果として、関数呼び出し ----------- ------------------------ Person->new() Person::new("Person") Employee->new() Person::new("Employee") =begin original So don't use function calls when you mean to call a method. =end original ですので、メソッドを呼ぼうとしているときに関数呼び出しを使わないでください。 =begin original 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. =end original 従業員がただの Person だったら、それはあまり面白くありません。 さあ、他のメソッドを追加しましょう。 従業員に、データフィールドを設けて、従業員の給与や、従業員 ID や、入社日に アクセスしましょう。 =begin original 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: =end original これらのオブジェクトのデータを取得するような、ほとんど同じメソッドたちを 作るのにちょっと飽きたとしても、落胆しないでください。 後で、こういった作業を短縮するためのいくつかの種々の便利な メカニズムについて説明します。 その逆に、単純なやりかたは次のものです: 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 Overridden Methods (メソッドのオーバーライド) =begin original 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: =end original 派生クラスとその基底クラスの両方が同じ名前のメソッドを定義したら、 何が起きるでしょうか? たぶん、そのメソッドは派生クラスのもの(訳註:version)を得ます。 例えば、従業員で、peers()メソッドを呼ぶと、(訳註:Personとは、)少々違った 動きをさせたいとしましょう。 同僚の名前のリストをただ返す代わりに、ちょっと違った文字列を返しましょう。 次のようにします: $empl->peers("Peter", "Paul", "Mary"); printf "His peers are: %s\n", join(", ", $empl->peers); =begin original will produce: =end original 次のようになります: His peers are: PEON=PETER, PEON=PAUL, PEON=MARY =begin original To do this, merely add this definition into the Employee.pm file: =end original こうするためには、単に、この定義を Employee.pm ファイルに加えるだけです: sub peers { my $self = shift; if (@_) { @{ $self->{PEERS} } = @_ } return map { "PEON=\U$_" } @{ $self->{PEERS} }; } =begin original 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.) =end original ここで、ちょうど、I<多態性(polymorphism)> として広く知られている、大げさな コンセプトのデモンストレーションをしています。 存在するオブジェクトの形と振るまいを担い、われわれ自身の目的に 適応するように、存在するオブジェクトを変更します。 これは、不精の形です。 (polymorph させることは、魔法使いが、あなたを、蛙に 見せようと決めるときに起こることです)。 =begin original 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. =end original しばしば、派生クラス("サブクラス"としても知られるクラス)のもの (訳註: version)とその基底クラス("スーパークラス"としても知られるクラス)の もの(訳註: version)も同じように両方をきっかけをメソッドに呼ばせたいでしょう。 実際に、コンストラクタとデストラクタは、そうすることを望んでいそうですし、 先にみた、debug() メソッドでは、十中八九、そうだとうなずけます。 =begin original To do this, add this to Employee.pm: =end original そうするために、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 } =begin original 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 =end original お分かりのように、(訳註: Employee から)向きを変えて、Person パッケージの debug() 関数を呼びます。 ですが、良い設計にとっては、こうするのは、ひじょーに、壊れやすいものです。 Person が debug() 関数を持っておらず、I<その> debug() メソッドを 他のところから継承していたら、どうなるでしょう? 次のようにする方が良いです。 Person->debug($Debugging); =begin original But even that's got too much hard-coded. It's somewhat better to say =end original ですが、まだハードコードしすぎです。 次のようにする方が良いです。 $self->Person::debug($Debugging); =begin original 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. =end original これは、Person 内で、debug() メソッドを探し始める楽しいやりかたです。 この作戦は、オーバーライドされたクラスメソッドよりも、 オーバーライドされたオブジェクトメソッドで、よく見ます。 =begin original 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. =end original 少しのものがまだあります。 スーパークラスの名前をハードコードしています。 継承するクラスを変えるか、他のものを加えたら、このことは特に悪いです。 幸運なことに、仮名クラスの SUPER がここで助けになります。 $self->SUPER::debug($Debugging); =begin original 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. Note that C refers to the superclass of the current package, I to the superclass of C<$self>. =end original こうすると、自分のクラスの @ISA をのぞき始めます。 これは、メソッドコール I<内> から意味をなすだけです。 他のどこからも、SUPER:: の何にも、アクセスしようとしないでください。 というのは、上書きされたメソッド呼出の外側には存在しないからです。 C は現在のパッケージのスーパークラスを参照するのであって、 C<$self> のスーパークラス I<ではない> ことに注意してください。 =begin original 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: =end original 事態はちょっと複雑になってきています。 してはならないことをしたでしょうか? これまでのように、まともなクラスかどうかをテストする一つの方法は、 空のサブクラステストによるものです。 すでに、チェックしている Employee クラスがあるので、 Employee から新しい空のサブクラスを生成できます。 次のものです: package Boss; use Employee; # :-) @ISA = qw(Employee); =begin original And here's the test program: =end original テストプログラムです: #!/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->as_string, $boss->age; printf "His peers are: %s\n", join(", ", $boss->peers); =begin original 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: =end original 実行すると、まだ大丈夫です。 素敵なフォーマットで、デバッガで 'x' コマンドを働かせる方法のように オブジェクトをダンプしたいなら、CPAN から、Data::Dumpler モジュールを 次のように使うことが出来ます: use Data::Dumper; print "Here's the boss:\n"; print Dumper($boss); =begin original Which shows us something like this: =end original 次のようなものを見せます: 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' ); =begin original 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: =end original ふーむ、何かがなくなっています。 給与、入社日、ID フィールドはどうでしょうか? たぶん、それらに何も、undef さえもセットしていません。 そのため、ハッシュのキーにそれらが見えなかったのです。 Employee クラスは、それ自身の new() メソッドがありません。 Person の new() メソッドは、Employee について知りません。 (また、そうすべきでもありません: 適切なオブジェクト指向設計はサブクラスが そのすぐ上のスーパークラスについて知っていてもよいと指示しています。 ですが、その逆は同様ではありません)。 では、Employee::new() を次のようにしましょう: sub new { my $class = shift; my $self = $class->SUPER::new(); $self->{SALARY} = undef; $self->{ID} = undef; $self->{START_DATE} = undef; bless ($self, $class); # reconsecrate return $self; } =begin original Now if you dump out an Employee or Boss object, you'll find that new fields show up there now. =end original Employee か Boss オブジェクトをダンプしたら、今度は、新しいフィールドが そこに現れるでしょう。 =head2 Multiple Inheritance (多重継承) =begin original 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++. =end original よし、初心者もオブジェクト指向のエキスパートも混乱させる危険をおかしても、 白状する時がきました。 Perl のオブジェクトシステムは、多重継承、または、略してMI として知られる、 賛否両論の考えを含んでいます。 これが意味するのは、次のことで全てです。 ただ一つの親クラス - 今度は、それ自身が親クラスやそのほかを持っている - を 持つのではなく、2 つ以上の親クラスを持つことが出来ることです。 多重継承の使うことで、トラブルに見まわれることもありますが、 C++ のようなあいまいなオブジェクト指向言語の Perl では、うまくいけば、 たいした問題にはならないこともあります。 =begin original 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 by default (see L for alternate method resolution orders). Consider a bunch of @ISA arrays like this: =end original 多重継承のやりかたは、実際、非常に簡単です: @ISA 配列に二つ以上の パッケージ名を置けばいいだけです。 Perl が、オブジェクトのために、メソッドを見つけに行く時がきたら、 順番に @ISA のパッケージをそれそれ見ます。 えっと、かなり。 完全に再帰的で、デフォルトでは深さ優先です(その他の順序解決手法については L を参照してください)。 次のような @ISA 配列の組合せを考えてください: @First::ISA = qw( Alpha ); @Second::ISA = qw( Beta ); @Third::ISA = qw( First Second ); =begin original If you have an object of class Third: =end original Third クラスのオブジェクトがあるとすると: my $ob = Third->new(); $ob->spin(); =begin original 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. =end original spin() メソッド(または、さらに言えば、new())をどのように 見つけるのでしょうか? 検索は、深さ優先なので、クラスは次の順番で調べられます: Third, First, Alpha, Second, Beta の順です。 =begin original 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. =end original 実際には、多重継承が使われているクラスモジュールは、ほとんどみかけません。 ほとんどいつも、多重継承ではなく、一つのクラスは他の一つのクラスに 含まれているという単純なコンテナ関係を選びます。 これが、なぜ Person オブジェクトは、Fullname オブジェクトを I<含んでいる> かという理由です。 これは、Person オブジェクトが Fullname オブジェクトで I<あった> と いうことを意味しません。 =begin original 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.) =end original しかしながら、Perl での多重継承が見境のない、一つの特別な領域があります: 他のクラスのクラスメソッドを借りてくることです。 このことは、幾分普及しており、 バンドルされている「オブジェクトのない」クラスで特にそうです。 Exporter や、DynaLoader や、AutoLoader や、SelfLoader がそうです。 これらのクラスは、コンストラクタを提供しません。 これらのクラスは、(訳註: 他のクラスから)クラスメソッドを 継承するかもしれないので、存在しています。 =begin original For example, here is the POSIX module's @ISA: =end original たとえば、POSIX モジュールの @ISA は次のようになっています: package POSIX; @ISA = qw(Exporter DynaLoader); =begin original 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. =end original POSIX モジュールは、実際には、オブジェクトモジュールではありません。 ですが、Exporter も DynaLoader も、そうです。 Exporderと、DynaLoader クラスは、クラスメソッドの振るまいを POSIX に、 貸しているだけです。 =begin original 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. =end original なぜ、オブジェクトメソッドに、多重継承が使われないのでしょうか? 理由の一つは、複雑な副作用がありうるからです。 まず一つ例をあげると、継承のグラフ(ツリーではなく)が、同じ基底クラスに もどって集中します。 Perlは、再帰的な継承に対して防御していますが、単に、共通の祖先を通して、 お互いに関連している親を持つことは、近親相姦に思えても、禁止されていません。 もし、先ほど見た Third クラスで、new() メソッドが、Third クラスの 2 つの 親クラスで、オーバーライドされたコンストラクタを両方呼ぶとしたら、 どうなるんでしょう? SUPER 表記は、最初の一つしか見つけません。 Alpha と Beta クラスの両方が、共通の祖先、たとえば Nought クラスを 持っていたらどうでしょうか? オーバーライドされたメソッドを呼ぶ継承ツリーを登り続けるなら、結局、 Nought::new() を二度呼ぶことになります。 たぶん、それは、悪い考えでしょう。 =head2 UNIVERSAL: The Root of All Objects (UNIVERSAL: 全てのオブジェクトの根っこ) =begin original 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. =end original 全てのオブジェクトが、いくつかの根本的な基底クラスに根付いていたら、 便利でしょうか? すべてのオブジェクトに共通のメソッドを与えるのに、それぞれの @ISA に クラスを加えずにできる方法です。 それで、そうできることがわかります。 あなたはそれを見ることはありませんが、Perl は暗黙にかつ決定的に、 @ISA の終わりに特別な要素があることを想定しています: UNIVERSAL クラスです。 5.003 では、UNIVERSAL クラスにあらかじめ定義されているメソッドは ありませんでしたが、UNIVERSAL クラスにいれたいようなものは、なんでも 置くことが出来ました。 =begin original 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: =end original しかし、5.004 (または、5.003_08 のような、いくつかの破棄的なリリース)より、 UNIVERSAL には、既にいくつかのメソッドがあります。 これらのメソッドは Perl バイナリに組み込まれており、そのため、それらを ロードするのに余計な時間はかかりません。 あらかじめ定義されているメソッドは、isa(), can(), VERSION() です。 isa() はオブジェクトかクラスが、階層構造を横断することなく、 別のクラス「である」かどうかを教えます: $has_io = $fd->isa("IO::Handle"); $itza_handle = IO::Socket->isa("IO::Handle"); =begin original 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: =end original can() メソッドは、オブジェクトかクラスに対して呼ばれて、その文字列の引数が そのクラスで、呼ぶことの出来るメソッドかどうかを帰って報告します。 実際、そのメソッドに関数のリファレンスを返します: $his_print_method = $obj->can('as_string'); =begin original 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: =end original 最後に、VERSION メソッドは、クラス(または、オブジェクトのクラス)が、 $VERSION と呼ばれるパッケージのグローバル変数が十分に高いかどうかを チェックします; 次のように: Some_Module->VERSION(3.0); $his_vers = $ob->VERSION(); =begin original 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 =end original しかし、ふつう、VERSION を自分自身には呼びません。 (次のことを覚えておいてください。 すべての大文字の関数名は、Perl の慣例で、その関数が、なんらかの方法で、 Perl によって自動的に使われるだろうということを示しています。) このケースでは、次のようにすると同じことが起こります: use Some_Module 3.0; =begin original If you wanted to add version checking to your Person class explained above, just add this to Person.pm: =end original 上に説明した Person クラスでバージョンのチェックを加えたいなら、 Person.pm に、次のことを加えるだけです: our $VERSION = '1.1'; =begin original and then in Employee.pm you can say =end original そして、Employee.pm で、次のようにできます: use Person 1.1; =begin original 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. =end original このことで、少なくともそのバージョン番号か、それより高いものが利用可能だと 確かめます。 正確なバージョン番号でのロードなので、同じではありません。 現在のところ、あるモジュールの複数のバージョンを同時にインストールする 機構はありません。 嘆かわしい。 =head2 Deeper UNIVERSAL details (より深い UNIVERSAL の詳細) =begin original It is also valid (though perhaps unwise in most cases) to put other packages' names in @UNIVERSAL::ISA. These packages will also be implicitly inherited by all classes, just as UNIVERSAL itself is. However, neither UNIVERSAL nor any of its parents from the @ISA tree are explicit base classes of all objects. To clarify, given the following: =end original (おそらくほとんどの場合で賢明ではないですが) @UNIVERSAL::ISA に他の パッケージ名を入れることもできます。 これらのパッケージも UNIVERSAL 自身と同様、全てのクラスによって 暗黙的に継承されます。 しかし、UNIVERSAL も @ISA 木によるその親も、全てのオブジェクトの明示的な 基底クラスにはなりません。 明確化するために、以下のコードを見てみます: @UNIVERSAL::ISA = ('REALLYUNIVERSAL'); package REALLYUNIVERSAL; sub special_method { return "123" } package Foo; sub normal_method { return "321" } =begin original Calling Foo->special_method() will return "123", but calling Foo->isa('REALLYUNIVERSAL') or Foo->isa('UNIVERSAL') will return false. =end original Foo->special_method() を呼び出すと "123" を返しますが、 Foo->isa('REALLYUNIVERSAL') や Foo->isa('UNIVERSAL') を呼び出すと偽を 返します。 =begin original If your class is using an alternate mro like C3 (see L), method resolution within UNIVERSAL / @UNIVERSAL::ISA will still occur in the default depth-first left-to-right manner, after the class's C3 mro is exhausted. =end original あなたのクラスが C3 のようなその他の mro を使っている場合 (L を 参照してください)、UNIVERSAL / @UNIVERSAL::ISA 内でのメソッド解決は、 クラスの C3 mro が終了後、デフォルトの深さ優先左から右の方式で行われます。 =begin original All of the above is made more intuitive by realizing what really happens during method lookup, which is roughly like this ugly pseudo-code: =end original 上記の全ては、メソッド検索中に実際に何が起きるのかを実感することで より分かりやすくなります; これはおおよそ以下のような醜い擬似コードの ようになります: =begin original get_mro(class) { # recurses down the @ISA's starting at class, # builds a single linear array of all # classes to search in the appropriate order. # The method resolution order (mro) to use # for the ordering is whichever mro "class" # has set on it (either default (depth first # l-to-r) or C3 ordering). # The first entry in the list is the class # itself. } =end original get_mro(class) { # クラスの @ISA の開始から再帰して、適切な順序の # 検索する全てのクラスの単一の線形の配列を作成します。 # 使用されるメソッド解決順序 (mro) は、これにセットされている # mro「クラス」によります(デフォルト(深さ優先左から右)か # C3 順序のどちらかです)。 # このリストの最初の要素はこのクラス自身です。 } find_method(class, methname) { foreach $class (get_mro(class)) { if($class->has_method(methname)) { return ref_to($class->$methname); } } foreach $class (get_mro(UNIVERSAL)) { if($class->has_method(methname)) { return ref_to($class->$methname); } } return undef; } =begin original However the code that implements UNIVERSAL::isa does not search in UNIVERSAL itself, only in the package's actual @ISA. =end original しかし、UNIVERSAL::isa を実装したコードは UNIVERSAL 自身では検索せず、 パッケージの実際の @ISA のみを検索します。 =head1 Alternate Object Representations (ハッシュに代わるオブジェクトの表現) =begin original 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. =end original オブジェクトはハッシュリファレンスとして実装される必要はありません。 オブジェクトは、うまく bless されるリファレンスでありさえすれば、どんな 種類のリファレンスでも可能です。 このことは、スカラリファレンスでも、配列リファレンスでも、 コードのリファレンスでも、格好の的となるということです。 =begin original 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. =end original スカラは、オブジェクトがたった一つの値しか持たないなら、うまくいきます。 配列は、ほとんどのケースで、うまくいきます。 ですが、継承を少々危うくします。 派生クラスのために、新しい索引を作り上げなければならないからです。 =head2 Arrays as Objects (オブジェクトとして配列を) =begin original 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. =end original クラスを使う人が、契約を支持し、公示されたインターフェースに我慢するなら、 その基礎を成すインターフェースを、そうしたければ変えることが出来ます。 これは同じインターフェースの仕様に合う、もう一つの実装です。 さて、オブジェクトを表現するのに、ハッシュリファレンスの代わりに、 配列リファレンスを使いましょう。 package Person; use strict; my($NAME, $AGE, $PEERS) = ( 0 .. 2 ); =begin original ############################################ ## the object constructor (array version) ## ############################################ 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; } =end original ############################################ ## オブジェクトコンストラクタ (配列版) ## ############################################ 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; # so the require or use succeeds =begin original 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. =end original 配列アクセスはハッシュアクセスより、だいぶ速いと思うかもしれません。 ですが、この2つは、実際は、類似のものです。 配列は、I<ちょっと> 速いです。 ですが、10 とか、15 パーセントも速くはありません; たとえ、上の $AGE のような文字の変数を、1 のような数字に置き換えても、です。 二つの手法のより大きな違いは、メモリの使用で見つけられます。 ハッシュでの表現は、配列での表現よりもメモリを多く消費します。 値と同じように、キーにも、メモリを割り当てなければならないからです。 しかし、そのことは、本当に、そんなに悪いことではありません。 特に、5.004 からは、ハッシュにキーを与えるために、メモリは一度 割り当てられるだけです。 いくつのハッシュがキーを持つのかは問題ではありません。 今後、この 2 つの違いは、より効率的な基礎となる表現が工夫されるにつれ、 あいまいに消滅していくだろうと、期待されています。 =begin original 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. =end original まだ、スピード(と、メモリで、幾分大きくなるところ)で、ちょっと 優れていることは、プログラマに、単純なクラスのために配列表現を 選ばせるのに十分です。 やはり、拡張性にちょっとした問題があります; 後年、サブクラスを作ろうとと思ったときに、ハッシュがちょうどうまく 働くことがわかるでしょうから。 =head2 Closures as Objects (オブジェクトとしてクロージャを) =begin original 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? :-) =end original オブジェクトを表現するのに、コードリファレンスを使うことは、魅力ある将来性を 与えます。 世界中で唯一人しか、オブジェクトのデータを見ることが出来ない、 新しい匿名の(クロージャ)関数を作ることが出来ます。 というのは、データをレキシカルにしか見えない無名ハッシュに置くからです。 つまり、クロージャを作り、bless し、オブジェクトとして返すからです。 このオブジェクトメソッドは、一変して、普通のサブルーチン呼び出しとして クロージャを呼び、影響を与えたいフィールドに、それを渡します。 (はい、二重の関数呼び出しは、遅いです。 ですが、もし、速さを求めるのなら、オブジェクトを全く使わなければいいんです。 そうでしょ? :-) =begin original Use would be similar to before: =end original 使いかたは、前と似ています: 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"; =begin original but the implementation would be radically, perhaps even sublimely different: =end original ですが、実装は、根本的に、たぶん、圧倒的なやりかたで、違っています: package Person; sub new { my $class = shift; 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; =begin original 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. =end original なぜなら、オブジェクトがコードリファレンスの背後に 隠されているからです。 このことはちょっとミステリアスです; クロージャの由来する関数型プログラミング言語よりも、 標準的な手続き型や、オブジェクトベースのプログラミング言語の方に よりしっかり根付いているからです。 new() メソッドで作られて、返されたオブジェクトは、今まで見てきたような、 データのリファレンスではありません。 オブジェクトは、匿名のコードリファレンスであり、内部に、特定の バージョン(レキシカルにバインドしており、インスタンス化している)の - プライベートな変数 $self に蓄えられた - オブジェクトデータにアクセスする コードを持っています。 それは、毎回、同じ関数であるにもかかわらず、違ったバージョンの $self を 含みます。 =begin original 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. =end original C<$him-Ename("Jason")> のようなメソッドが呼ばれると、暗黙の 0 番目の 引数がデフォルトとして呼び出されます -- 全てのメソッド呼び出しと同様です。 ですが、この場合では、その引数は先ほどのコードリファレンスです(C++ での ポインタ関数のような何か、ですが、レキシカルな変数に深く バインドされています)。 コードリファレンスを呼ぶこと以上に、コードリファレンスですることは 多くはありません。 つまり、このときするのは、C<&{$_[0]}> とすることだけです。 これは、単なる普通の関数呼び出しであり、メソッド呼び出しではありません。 最初の引数は、文字列 "NAME" であり、残りの引数は、メソッドに 渡されているもの全てです。 =begin original 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. =end original new() で作られたクロージャの内側で実行されると、$self ハッシュリファレンスは 突然に見えるようになります。 クロージャは、その最初の引数(このケースでは、'NAME' です。 name() メソッドがそれを渡したので)をつかんで、その文字を、ユニークな バージョンの $self のプライベートで隠されたハッシュへの添字に使います。 =begin original 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. =end original この世で、誰も、実行されているメソッドの外側にいるものには、 この隠されたデータに近付けることを許されていません。 ええ、ほとんどありません。 デバッガを使っているプログラムを通すステップを選び、そのメソッドにいる間、 そのかけらを見つけることが I<できます>。 ですが、他の全ての人には、運がありません。 =begin original 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. =end original もし、このことが Scheme なみなさんを興奮させなければ、何が 興奮させるのかわかりません。 このテクニックの、C++ や、Java や、他の脳死状態の静的な言語への翻訳が、 このキャンプの熱狂的なファンのくだらない課題としては、残っていますが。 =begin original 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. =end original caller() 関数で、ちょっとした詮索を加えることが出来ますし、クロージャが それ自身のパッケージを呼ばない限り、動作を拒否させることも出来ます。 このことは、まちがいなく、プログラミングポリスと、その親類の厳格な人の、 ある種の潔癖な関心事を満足させるでしょう。 =begin original 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.) =end original もしも、いつ、(プログラマの三大美徳である) 傲慢が開始するのかを疑問に 思っていたなら、ここにあります。 (もっとまじめにいうなら、傲慢は、ちょっとしたすばらしくよく設計された コードを書くことから生じる腕前のプライドです)。 =head1 AUTOLOAD: Proxy Methods (AUTOLOAD: 代理メソッド) =begin original 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. =end original オートロードは、未定義のメソッドの呼び出しをインターセプトする方法です。 オートロードルーチンは、その場で、新しい関数 - ディスクから ロードされるか、たぶん eval されているもの - を作ることを選ぶかもしれません。 この「その場で定義する」戦略が、オートローディングと呼ばれる理由です。 =begin original 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. =end original ですが、これはたった一つの可能な手法です。 もう一つの手法は、オートロードされたメソッドそれ自身に、直接、要求された サービスを提供させることです。 この方法を使ったとき、オートロードされたメソッドを「代理」メソッドのように、 考えるかもしれません。 =begin original 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. =end original Perlが特定のパッケージの未定義の関数を呼ぼうとし、その関数が 定義されていない場合、同じパッケージにある AUTOLOAD と呼ばれる関数を 探します。 もし、AUTOLOAD があれば、元の関数が持っていたのと同じ引数で、それが 呼ばれます。 その関数の完全修飾名は、パッケージのグローバル変数 $AUTOLOAD に 蓄えられます。 いったん呼ばれると、関数は、好きなように何かをすることが出来ます; 適当な名前で、新しい関数を定義すること、実際に装飾的な一種の、C を、 それに対して正しく行うこと、コールスタックからそれ自身を消すことを、 含みます。 =begin original 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. =end original これはオブジェクトと何が関係しますか? 結局、関数について話し続けているのであって、メソッドについてではありません。 たぶん、メソッドは、単に特別な引数と、それが見つけれらる場所について、 装飾的な記法を伴ったただの関数なので、オートローディングをメソッドとしても 使うことが出来ます。 Perl は、@ISA を通した再帰的な捜索に疲れ果てるまで、AUTOLOAD メソッドを 探し始めません。 どんな種類のオブジェクトに対する、未解決のメソッド呼び出しを トラップするために、UNIVERSAL::AUTOLOAD メソッドを定義する、 プログラマがいることも知られています。 =head2 Autoloaded Data Methods (オートロードされるデータメソッド) =begin original 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. =end original 最初に Person クラスと、それから、Employee クラスを見せた、はるか前に 遡ったら、二重化されたコードについて、おそらく、少し疑いを 持ち始めるでしょう。 それぞれのメソッドは、仮想的にまったく同じに見えるハッシュのフィールドに アクセスしていました。 このことは、偉大なプログラミングの美徳である、短気をくすぐります。 ですが、このときに、不精を勝たせて、なにもしません。 代理メソッドが、これを癒せます。 =begin original 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". =end original 新しいデータフィールドをが欲しいと思うたびに新しい関数を毎回書く代わりに、 オートロードのメカニズムを使って、(実際に、偽の)メソッドをその場で 生み出します。 妥当なメンバにアクセスしていることを証明するために、 C<_permitted>("under-permitted" と発音します)フィールドでチェックします。 このフィールドは、%field と呼ばれるレコードの中の許されたフィールドの、 ファイルスコープのレキシカルな(C のファイル static のような)ハッシュ リファレンスです。 なぜ、アンダースコアがあるのか? かつて使った、_CENSUS フィールドと同じ理由のためです: 「内部的に使うためだけ」を意味するマークです。 =begin original Here's what the module initialization code and class constructor will look like when taking this approach: =end original ここにある、モジュールの初期化コードとクラスのコンストラクタは、 このアプローチを取る場合に見るようなものです: package Person; use Carp; our $AUTOLOAD; # it's a package global my %fields = ( name => undef, age => undef, peers => undef, ); sub new { my $class = shift; my $self = { _permitted => \%fields, %fields, }; bless $self, $class; return $self; } =begin original If we wanted our record to have default values, we could fill those in where current we have C in the %fields hash. =end original もし、レコードに、デフォルトの値を持たせたいなら、現在の、%field ハッシュに C のあるところに、それらを埋めることが出来ます。 =begin original 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. =end original オブジェクト自身に、クラスデータのリファレンスを保存させたやりかたに 気づいたでしょうか? 直接に %fields を参照するメソッドを持つか、そのほか、礼儀正しい継承を 持たない代わりに、オブジェクトを通してクラスデータにアクセスすることが 重要であることを思いだしてください。 =begin original 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. =end original けれども、本当の魔法は、代理メソッドにあります。 代理メソッドは、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}; } } =begin original Pretty nifty, eh? All we have to do to add new data fields is modify %fields. No new functions need be written. =end original とっても素敵でしょ? 新しいデータフィールドを加えるときにしなければならないことは、 %fields を変更することだけです。 新しい関数を書く必要はありません。 =begin original 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. =end original C<_parmitted> フィールドを、完全に避けることが出来ましたが、どのように オブジェクトのクラスデータをリファレンスに蓄えるのかを実証したかったのです。 ですので、オブジェクトメソッドから、直接に、クラスデータにアクセスする 必要はありません。 =head2 Inherited Autoloaded Data Methods (継承されるオートロードされるデータメソッド) =begin original But what about inheritance? Can we define our Employee class similarly? Yes, so long as we're careful enough. =end original しかし、継承ではどうなるのでしょう? Employeeクラスを同じように定義できるでしょうか? できます、十分に気をつける限りは。 =begin original Here's how to be careful: =end original 気をつけ方です: package Employee; use Person; use strict; our @ISA = qw(Person); my %fields = ( id => undef, salary => undef, ); sub new { my $class = shift; my $self = $class->SUPER::new(); my($element); foreach $element (keys %fields) { $self->{_permitted}->{$element} = $fields{$element}; } @{$self}{keys %fields} = values %fields; return $self; } =begin original 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. =end original これをしたら、Employee パッケージに、AUTOLOAD 関数を持つ必要はありません。 というのは、継承を通して、Person のバージョンを把握し、全て、 うまく動くからです。 =head1 Metaclassical Tools (メタクラスなツールたち) =begin original 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. =end original 代理メソッドが、データメソッドを関数としてくどくどコーディングするよりも、 より構造体風なクラスを作るのに、便利なアプローチを提供するといっても、 まだ、好ましいものが少し残されています。 第一には、代理メソッドを通してトラップさせるつもりのない、 いんちきの呼び出しを取り扱う必要があることを意味します。 上で詳細を述べたように、継承を扱う時に非常に慎重にならなければならないことも 意味します。 =begin original 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. =end original Perl プログラマは、さまざまなクラス生成クラスを作ることで、 これに対応しています。 これらのメタクラスは他のクラスを作るクラスです。 見るべき組は、Class::Struct と、Alias です。 これらと、他の関連するメタクラスは、CPAN のモジュールディレクトリで 見つけられます。 =head2 Class::Struct =begin original 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. =end original その古いものの一つは、Class::Struct です。 実際、その構文とインターフェースは、perl5 が実際のものに固まるだいぶ前に、 スケッチされました。 Class::Struct は、特定の型のフィールドがあるようなオブジェクトを持つクラスを 「宣言」する方法を提供します。 それが呼ばれる関数は、驚くようなものではなく、struct() です。 構造、またはレコードは、Perl では、基本の型ではないので、 レコード風なオブジェクトを提供するクラスを作るたびに、new() メソッドと、 それに加えて、別個に、レコードの各フィールドのために、 データアクセスメソッドを定義しなければなりません。 このプロセスに、すぐに飽きてしまうでしょう。 Class::Struct::struct 関数はこの退屈なことを緩和します。 =begin original Here's a simple example of using it: =end original これを使う簡単な例です: use Class::Struct qw(struct); use Jobbie; # user-defined; see below struct 'Fred' => { one => '$', many => '@', profession => 'Jobbie', # does not call Jobbie->new() }; $ob = Fred->new(profession => Jobbie->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); =begin original 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. =end original struct の中で、型を宣言でき、それは基本的な Perl の型になるか、 ユーザー定義の型(クラス)になります。 ユーザー型は、そのクラスのnew()メソッドを呼ぶことによって、初期化されます。 =begin original Take care that the C object is not created automatically by the C class's new() method, so you should specify a C object when you create an instance of C. =end original C オブジェクトは C クラスの new() メソッドで自動的には 作成されないので、C の実態を作成するときに C オブジェクトを 指定することに注意してください。 =begin original 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. =end original 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); =begin original Here's how to do this using the Class::Struct module. The crux is going to be this call: =end original Class::Struct モジュールを使ってこれをする方法です。 最重要ポイントは、この呼び出しです: struct 'Net::hostent' => [ # note bracket name => '$', aliases => '@', addrtype => '$', 'length' => '$', addr_list => '@', ]; =begin original Which creates object methods of those names and types. It even creates a new() method for us. =end original この呼び出しは、上記の名前と型のオブジェクトメソッドを作ります。 new() メソッドさえも作ります。 =begin original We could also have implemented our object this way: =end original 次の方法でも、オブジェクトを実装できましたが、しませんでした: struct 'Net::hostent' => { # note brace name => '$', aliases => '@', addrtype => '$', 'length' => '$', addr_list => '@', }; =begin original 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. =end original こうすると、Class::Struct は、オブジェクト型を、無名配列の代わりに、 無名ハッシュを使います。 配列は、ハッシュより速く、小さいですが、ハッシュは、継承をしたいときに、 よく働きます。 この構造体風なオブジェクトには、継承を考えていないので、今回は、 よりよいスピードと、サイズに余裕をもたせることにしました。 =begin original Here's the whole implementation: =end original 実装は次のようになります: 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; =begin original # Class::Struct forbids use of @ISA sub import { goto &Exporter::import } =end original # 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; =begin original 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. =end original 動的なクラスの作成に加えて、コアな関数のオーバーライドや、 import/export の例や、関数のプロトタイピングや、C<&whatever> を通しての 関数のショートカット呼び出しや、C での 関数の置き換えなどの他のコンセプトの正しい具体例を忍び込ませています。 これらの全ては、大半が、伝統的なモジュールの観点から意味のあるものです。 ですが、お分かりのように、オブジェクトモジュールとして、それらを使うことも 出来ます。 =begin original 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. =end original 他の、オブジェクトベースのものや、File::stat、Net::hostent、Net::netent、 Net::protoent、Net::servent、Time::gmtime、Time::localtime、User::grent, User::pwent で、Perl の 5.004 リリースのコアな関数の構造体風な オーバーライドを見ることが出来ます。 これらのモジュールは、コンパイラのプログラムのためにとってある 慣例によって、全て小文字の最終的な構成要素を持っています。 これらが、コンパイルに影響し、組み込み関数を変更するからです。 これらは、C のプログラマがよく期待する型名を持っています。 =head2 Data Members as Variables (変数としてのデータメンバ) =begin original 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. =end original C++ オブジェクトをよく使うなら、メソッド内からオブジェクトのデータメンバを 単純な変数のように得ることが出来るのになれているでしょう。 Alias モジュールは、これを提供します。 同時に、ちょっとだけよいのは、オブジェクトは呼ぶことが出来るけれど、 クラスの外側のみんなは呼ぶことの出来ない、 プライベートなメソッドのようなところです。 =begin original 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? =end original Alias モジュールをつかって Person を作る例です。 これらの魔術的なインスタンス変数を更新すると、自動的にハッシュの値の フィールドを更新します。 便利でしょ? package Person; # this is the same as before... sub new { my $class = shift; 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; } =begin original 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(). =end original C を宣言しなければならないのは、Alias がしているのが、 フィールドと同じ名前のパッケージのグローバル変数をいじれるようにするからです。 要するに、C をしながら、グローバル変数を使うために、 これらを、先に宣言しなければなりません。 これらのパッケージの変数は、ちょうど、それらに、local() を使ったように、 attr() 呼び出しを囲んでいるブロックにローカライズされています。 しかし、このことは、ちょうど、他の local() のように、まだ、一時的な値で、 グローバル変数をで考えていることを意味します。 =begin original It would be nice to combine Alias with something like Class::Struct or Class::MethodMaker. =end original Alias と、CLass::Structや、Class::MethodMaker を 混ぜて使うと良いでしょう。 =head1 NOTES (注意) =head2 Object Terminology (オブジェクト専門用語) =begin original 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. =end original さまざまなオブジェクト指向文献で、たくさんの違った言葉がほんの少ししか 違わない概念を表すのに使われているように思います。 もし、あなたがまだオブジェクト指向プログラマではないなら、 これらの、気まぐれな言葉に悩むことはありません。 ですが、もし、すでに、オブジェクト指向プログラマなら、Perl で、同じ コンセプトをどのように表すのか知りたいでしょう。 =begin original 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. =end original 例えば、オブジェクトをクラスの I<インスタンス >と呼ぶことや、それら インスタンスのオブジェクトメソッドを I<インスタンスメソッド> と呼ぶことは、 一般的でしょう。 オブジェクトごとに特有のデータフィールドはよく、I<インスタンスデータ> とか、 I<オブジェクト属性> と呼ばれ、全てのクラスのメンバに共通のデータフィールドは I<クラスデータ> や、I<クラス属性> や、I<静的データメンバ> と よく呼ばれるでしょう。 =begin original Also, I, I, and I all describe the same notion, whereas I, I, and I describe the other related one. =end original また、I<基底クラス> や、I<一般クラス> や I<スーパークラス> など全てが、 同じ考えで記述します。 ですので、I<派生クラス> や I<特定クラス> や、 I<サブクラス> は、他の関連するものを記述します。 =begin original 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. =end original C++ プログラマには、I<静的メソッド> や I<仮想メソッド> がありますが、 Perl プログラマには、I<クラスメソッド> と、 I<オブジェクトメソッド> しかありません。 メソッドが、クラス/オブジェクトメソッドとして使われるかどうかは、 使いかたによるだけです。 うっかりと、オブジェクト(リファレンスを期待するもの)で クラスメソッド(文字列の引数を期待するもの)を呼ぶことも出来ますし、 その逆も出来ます。 =begin original 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. =end original C++ の観点からは、Perl の全てのメソッドは、仮想的です。 ところで、このことは、メソッドが、普通の組み込み関数やユーザ定義関数が 出来るような、引数リストで関数のプロトタイプを、チェックされない理由です。 =begin original 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. =end original クラスは、それ自身、オブジェクトの何かですので、Perl のクラスは、 "メタオブジェクトとしてのクラス"(または、I<オブジェクト工場> とも 呼ばれます)哲学と、"型定義としてのクラス"(振る舞いを I<宣言> し、 メカニズムを I<定義しない>)考えの両方を表すものとして見られます。 C++ は、後者をサポートしますが、前者は、サポートしません。 =head1 SEE ALSO =begin original The following manpages will doubtless provide more background for this one: L, L, L, L, L, and L. =end original 以下のマニュアルページは、間違いなく、このマニュアルページに多くの 背景を与えてくれます: L, L, L, L, L, L。 =begin original L is a kinder, gentler introduction to object-oriented programming. =end original L は、よりやさしい、オブジェクト指向プログラミングの 紹介です。 =begin original L provides more detail on class data. =end original L はクラスデータに関する詳細を提供します。 =begin original Some modules which might prove interesting are Class::Accessor, Class::Class, Class::Contract, Class::Data::Inheritable, Class::MethodMaker and Tie::SecureHash =end original 以下のモジュールは関心をひくでしょう: Class::Accessor, Class::Class, Class::Contract, Class::Data::Inheritable, Class::MethodMaker, Tie::SecureHash =head1 AUTHOR AND COPYRIGHT (著者および著作権) 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 COPYRIGHT (著作権) =head2 Acknowledgments (謝辞) 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. =begin meta Translate: Kato Atsushi (5.8.0) Update: SHIRAKATA Kentaro (5.10.0-) Status: completed =end meta