Example7.1

「Example7.1」の編集履歴(バックアップ)一覧に戻る
Example7.1」を以下のとおり復元します。
** 7.1 Case Classes and Case Objects

Case classes and case objects are defined like a normal classes or objects, except that the definition is prefixed with the modifier case. For instance, the definitions 

「ケースクラス」と「ケースオブジェクト」は普通のクラスやオブジェクトのように定義されますが、定義に修飾子 case が前に付く事がだけが違います。例えば定義

 abstract class Expr 
 case class Number(n: Int) extends Expr 
 case class Sum(e1: Expr, e2: Expr) extends Expr 

introduce Number and Sum as case classes. The case modifier in front of a class or object definition has the following effects. 

は Number と Sum をケースクラスとして導入します。クラスやオブジェクト定義の前の case 修飾子は次の様な効果があります。

1. Case classes implicitly come with a constructor function, with the same name as the class. In our example, the two functions 

1. ケースクラスは暗黙的にコンストラクタ関数を伴い、それはクラスと同じ名前です。我々の例の場合、二つの関数

 def Number(n: Int) = new Number(n) 
 def Sum(e1: Expr, e2: Expr) = new Sum(e1, e2) 

would be added. Hence, one can now construct expression trees a bit more concisely, as in 

が追加されます。従って式の木をもう少し簡潔に次の様に構成出来ます。

 Sum(Sum(Number(1), Number(2)), Number(3))

2. Case classes and case objects implicitly come with implementations of methods toString, equals and hashCode, which override the methods with the same name in class AnyRef. The implementation of these methods takes in each case the structure of a member of a case class into account. The toString method represents an expression tree the way it was constructed. So, 

2. ケースクラスとケースオブジェクトは暗黙的にメソッド toString, equals, hashCode を伴い、それらはクラス AnyRef の同名のメソッドをオーバライドします。これらのメソッドの実装はそれぞれのケースでケースクラスの構造を考慮しています。toString メソッドは式の木が構成された方法を表します。従って

 Sum(Sum(Number(1), Number(2)), Number(3))

would be converted to exactly that string, whereas the default implementation in class AnyRef would return a string consisting of the outermost constructor name Sum and a number. The equals methods treats two case members of a case class as equal if they have been constructed with the same constructor and with arguments which are themselves pairwise equal. This also affects the implementation of == and !=, which are implemented in terms of equals in Scala. So, 

はその文字列そのままに変換されます。一方、クラス AnyRef のデフォルトの実装は一番外側のコンストラクタの名前 Sum と数字からなる文字列を返すでしょう。equals メソッドはケースクラスの二つのケースメンバを、もし同じコンストラクタで構築されかつそれらの引数がそれぞれ等しいならば、等しいと扱います。これは == と != の実装にも影響しますが、それらは Scala では equals を用いて実装されているからです。従って

 Sum(Number(1), Number(2)) == Sum(Number(1), Number(2))

will yield true. If Sum or Number were not case classes, the same expression would be false, since the standard implementation of equals in class AnyRef always treats objects created by different constructor calls as being different. The hashCode method follows the same principle as other two methods. It computes a hash code from the case class constructor name and the hash codes of the constructor arguments, instead of from the object’s address, which is what the as the default implementation of hashCode does. 

は true を返します。もし Sum や Number がケースクラスでないならば、同じ式は false を返しますが、それはクラス AnyRef の equals の標準の実装では異なったコンストラクタ呼び出しで生成されたオブジェクトは常に異なると扱うからです。hashCode メソッドも他の二つのメソッドと同様の原則に従います。デフォルトの hashCode の実装が行うオブジェクトのアドレスからの計算の代わりに、ハッシュコードをケースクラスのコンストラクタ名とコンストラクタ引数のハッシュコードから計算します。

3. Case classes implicitly come with nullary accessor methods which retrieve the constructor arguments. In our example, Number would obtain an accessor method 

3. ケースクラスは暗黙的にコンストラクタ引数を取り出す引数無しアクセサメソッドを伴います。我々の例では、Number はアクセサメソッド

 def n: Int 

which returns the constructor parameter n, whereas Sum would obtain two accessor methods 

を持ち、コンストラクタ仮引数 n を返します。一方 Sum は二つのアクセサメソッドを持ちます。

 def e1: Expr, e2: Expr 

Hence, if for a value s of type Sum, say, one can now write s.e1, to access the left operand. However, for a value e of type Expr, the term e.e1 would be illegal since e1 is defined in Sum; it is not a member of the base class Expr. So, how do we determine the constructor and access constructor arguments for values whose static type is the base class Expr? This is solved by the fourth and final particularity of case classes. 

従って、例えば型 Sum の値 s に対して、左オペランドにアクセスする為に s.e1 と書く事が出来ます。しかし、型 Expr の値 e に対して項 e.e1 は正しくありませんが、それは e1 は Sum で定義されているのであって基底クラス Expr のメンバではないからです。では、静的型が基底クラス Expr である値に対してどうやってコンストラクタを判別してコンストラクタ引数にアクセスすれば良いのでしょうか?。これはケースクラスの四番目にして最後の特徴によって解決されます。

4. Case classes allow the constructions of patterns which refer to the case class constructor. 

4. ケースクラスではケースクラスのコンストラクタを参照する「パターン」の構築が可能です。

----
#comment

復元してよろしいですか?

ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。