Spec2.8Chap5a

「Spec2.8Chap5a」の編集履歴(バックアップ)一覧はこちら

Spec2.8Chap5a - (2011/02/03 (木) 20:19:53) の1つ前との変更点

追加された行は緑色になります。

削除された行は赤色になります。

* 第 5 章 クラスとオブジェクト &bold(){構文:} #co(){----------------------------------------------------- bgn-code} TmplDef ::= ['case'] 'class' ClassDef | ['case'] 'object' ObjectDef | 'trait' TraitDef #co(){----------------------------------------------------- end-code} #co(){----------------------------------------------------- bgn-hide0} Classes (§5.3) and objects (§5.4) are both defined in terms of templates . #co(){----------------------------------------------------- end-hide0} クラス(§5.3)とオブジェクト(§5.4)は共にテンプレートの観点で定義されています。 &br() &br() &aname(5.1,option=nolink){ } ** 5.1 テンプレート (Templates) &bold(){構文:} #co(){----------------------------------------------------- bgn-code} ClassTemplate ::= [EarlyDefs] ClassParents [TemplateBody] TraitTemplate ::= [EarlyDefs] TraitParents [TemplateBody] ClassParents ::= Constr {'with' AnnotType} TraitParents ::= AnnotType {'with' AnnotType} TemplateBody ::= [nl] '{' [SelfType] TemplateStat {semi TemplateStat} '}' SelfType ::= id [':' Type] '=>' | this ':' Type '=>' #co(){----------------------------------------------------- end-code} #co(){----------------------------------------------------- bgn-hide0} A template defines the type signature, behavior and initial state of a trait or class of objects or of a single object. Templates form part of instance creation expressions, class definitions, and object definitions. A template sc with mt1 with ... with mtn {stats} consists of a constructor invocation sc which defines the template's superclass, trait references mt1,...,mtn (n >= 0), which define the template's traits, and a statement sequence stats which contains initialization code and additional member definitions for the template. #co(){----------------------------------------------------- end-hide0} テンプレートは、クラス/トレイトあるいはオブジェクトあるいは シングルオブジェクト(訳注:シングルトンオブジェクトのこと?)の、 型シグニチャ、振る舞い、初期状態を定義します。 テンプレートは、 インスタンス生成式、クラス定義とオブジェクト定義等を形づくります。 テンプレート sc with mt1 with ... with mtn {stats} は、テンプレートの &italic(){スーパークラス}を定義するコンストラクタ呼び出し sc、 テンプレートの&italic(){トレイト}を定義するトレイト参照 mt1,...,mtn (n >= 0)、テンプレートの初期化コードと 追加のメンバー定義を含む文並び stats、からなります。 各トレイト参照 mti は、トレイト(§5.3.3)を表わします。 これと対照して、スーパークラスコンストラクタ sc は通常、トレイトではない クラスを参照します。 #co(){----------------------------------------------------- bgn-hide0} It is possible to write a list of parents that starts with a trait reference, e.g. mt1 with ... with mtn . In that case the list of parents is implicitly extended to include the supertype of mt1 as first parent type. The new supertype must have at least one constructor that does not take parameters. In the following, we will always assume that this implicit extension has been performed, so that the first parent class of a template is a regular superclass constructor, not a trait reference . #co(){----------------------------------------------------- end-hide0} トレイト参照で始まる親のリストを書くことが可能です。例えば、 mt1 with ... with mtn。 この場合、親のリストは、最初の親型として mt1 の スーパー型を含むように暗黙のうちに展開されます。 新しいスーパー型は、パラメータをとらない少なくとも 1 つのコンストラクタを 持っていなくてはなりません。 以降では、常にこの暗黙の展開が実行されると 想定します。ですから、テンプレートの最初の親クラスは、通常のスーパークラス コンストラクタであり、トレイト参照ではありません。 #co(){----------------------------------------------------- bgn-hide0} The list of parents of every class is also always implicitly extended by a reference to the scala.ScalaObject trait as last mixin. E.g. sc with mt1 with ... with mtn {stats } becomes mt1 with ... with mtn {stats } with ScalaObject {stats } . #co(){----------------------------------------------------- end-hide0} すべてのクラスの親のリストは同様に、最後のミックスインである scala.ScalaObject トレイトへの参照により、常に暗黙のうちに拡張されます。 つまり、 #co(){----------------------------------------------------- bgn-code} sc with mt1 with ... with mtn {stats } #co(){----------------------------------------------------- end-code} は、次になります。 #co(){----------------------------------------------------- bgn-code} mt1 with ... with mtn {stats } with ScalaObject {stats} #co(){----------------------------------------------------- end-code} テンプレートの親のリストは、正しい形でなければなりません。 #co(){----------------------------------------------------- bgn-hide0} This means that the class denoted by the superclass constructor sc must be a subclass of the superclasses of all the traits mt1,...,mtn . In other words, the non-trait classes inherited by a template form a chain in the inheritance hierarchy which starts with the template's superclass . #co(){----------------------------------------------------- end-hide0} これはスーパークラスコンストラクタ sc によって表されるクラスが、 すべてのトレイト mt1,...,mtn のスーパークラスのサブクラスでなければ ならないことを意味します。 言い換えれば、テンプレートによって継承される非トレイトクラスは、テンプレートの スーパークラスで始まる、継承階層の中で 1 つのチェインを形成します。 #co(){----------------------------------------------------- bgn-hide0} The least proper supertype of a template is the class type or compound type (§3.2.7) consisting of all its parent class types . #co(){----------------------------------------------------- end-hide0} テンプレートの&italic(){最小固有のスーパー型(least proper supertype)}とは、 そのすべての親クラス型から構成される複合型(§3.2.7)あるいはクラス型です。 #co(){----------------------------------------------------- bgn-hide0} The statement sequence stats contains member definitions that define new members or overwrite members in the parent classes. If the template forms part of an abstract class or trait definition, the statement part stats may also contain declarations of abstract members. If the template forms part of a concrete class definition, stats may still contain declarations of abstract type members, but not of abstract term members. Furthermore, stats may in any case also contain expressions; these are executed in the order they are given as part of the initialization of a template . #co(){----------------------------------------------------- end-hide0} 文並び stats は、新しいメンバーを定義するメンバー定義、あるいは 親クラス中のメンバーを上書きするメンバー定義を含みます。 もしテンプレートが抽象クラスあるいはトレイト定義を形づくるなら、文部分 stats も抽象メンバ宣言を含んでいて構いません。 もしテンプレートが具象クラス定義を形づくるなら、stats はそれでも、 抽象型メンバの宣言を含んでいても構いません。ただし、抽象項メンバの宣言は 含みません。 さらに、stats は、いずれの場合も式を含み得ます。; それらはテンプレートの初期化の一部として与えられた順に実行されます。 #co(){----------------------------------------------------- bgn-hide0} The sequence of template statements may be prefixed with a formal parameter definition and an arrow, e.g. x =>, or x :T =>. If a formal parameter is given, it can be used as an alias for the reference this throughout the body of the template. #co(){----------------------------------------------------- end-hide0} テンプレート文の並びには、形式上のパラメータ定義と矢印、たとえば、 x => あるいは x :T => 、が前につくことがあります。 もし形式上のパラメータが与えられていれば、それをテンプレート本体全体にわたって this 参照のエイリアスとして使えます。 #co(){----------------------------------------------------- bgn-hide0} If the formal parameter comes with a type T , this definition affects the self type S of the underlying class or object as follows: Let C be the type of the class or trait or object defining the template. If a type T is given for the formal self parameter, S is the greatest lower bound of T and C . If no type T is given, S is just C . Inside the template, the type of this is assumed to be S . #co(){----------------------------------------------------- end-hide0} もし形式上のパラメータが型 T と共にあるなら、その定義は、下地となっている クラス/オブジェクトの&italic(){自己型} S に次のような影響を与えます。: まず、C をテンプレートを定義するクラス/トレイト/オブジェクトの型であると 仮定します。 もし型 T が形式上の自己パラメータに対して与えられているなら、S は T と C の 最大の下限境界です。 もし型 T が与えられていないなら、S はたんに C です。 テンプレート中では、this の型は S であると想定されます。 #co(){----------------------------------------------------- bgn-hide0} The self type of a class or object must conform to the self types of all classes which are inherited by the template t . A second form of self type annotation reads just this: S =>. It prescribes the type S for this without introducing an alias name for it . #co(){----------------------------------------------------- end-hide0} クラスあるいはオブジェクトの自己型は、テンプレート t によって継承される すべてのクラスの自己型に適合しなくてはなりません。 自己型アノテーションの 2 つめの形は、たんに this: S => と書きます。 これにより、エイリアス名を導入せずに this の型 S を記述できます。 &bold(){Example 5.1.1} : 次のクラス定義を考えてください: #co(){----------------------------------------------------- bgn-code} class Base extends Object {} trait Mixin extends Base {} object O extends Mixin {} #co(){----------------------------------------------------- end-code} この場合、O の定義は次のように展開されます。 #co(){----------------------------------------------------- bgn-code} object O extends Base with Mixin {} #co(){----------------------------------------------------- end-code} &bold(){Java 型からの継承 :} テンプレートは、そのスーパークラスとして Java クラスを、 そのミックスインとして Java インターフェースを持っていても構いません。 &bold(){テンプレートの評価 :} #co(){----------------------------------------------------- bgn-hide0} Consider a template sc with mt1 with mtn {stats } . If this is the template of a trait (§5.3.3) then its mixin-evaluation consists of an evaluation of the statement sequence stats . #co(){----------------------------------------------------- end-hide0} テンプレート sc with mt1 mtn {stats } について考えます。 もしこれがトレイト(§5.3.3)のテンプレートなら、 その&italic(){ミックスイン評価}は、文並び stats の &italic(){評価}から構成されます。 #co(){----------------------------------------------------- bgn-hide0} If this is not a template of a trait, then its evaluation consists of the following steps . - First, the superclass constructor sc is evaluated (§5.1.1) . - Then, all base classes in the template's linearization (§5.1.2) up to the template's superclass denoted by sc are mixin-evaluated. Mixin-evaluation happens in reverse order of occurrence in the linearization . - Finally the statement sequence stats is evaluated . #co(){----------------------------------------------------- end-hide0} もしこれがトレイトのテンプレートでないなら、その評価は、 次のステップによって構成されます。 - 最初に、スーパークラスコンストラクタ sc が評価されます(§5.1.1)。 - 次に、sc によって表わわれるテンプレートのスーパークラスに至る、テンプレート線形化(§5.1.2)中のすべての基底クラスはミックスイン評価されます。ミックスイン評価は、線形化中での出現の逆順でされます。 - 最後に文並び stats が評価されます。 &br() &br() &aname(5.1.1,option=nolink){ } *** 5.1.1 コンストラクタ呼び出し (Constructor Invocations) &bold(){構文:} #co(){----------------------------------------------------- bgn-code} Constr ::= AnnotType {'(' [Exprs] ')'} #co(){----------------------------------------------------- end-code} #co(){----------------------------------------------------- bgn-hide0} Constructor invocations define the type, members, and initial state of objects created by an instance creation expression, or of parts of an object's definition which are inherited by a class or object definition. #co(){----------------------------------------------------- end-hide0} コンストラクタ呼び出しは、型、メンバー、そしてインスタンス生成式によって 生成されるオブジェクトの初期状態、あるいはクラス/オブジェクト定義によって 継承されたオブジェクト定義部分の初期状態等を定義します。 #co(){----------------------------------------------------- bgn-hide0} A constructor invocation is a function application x.c[targs](args1)...(argsn) , where x is a stable identifier (§3.1), c is a type name which either designates a class or defines an alias type for one, targs is a type argument list, args1,...,argsn are argument lists, and there is a constructor of that class which is applicable (§6.6) to the given arguments. If the constructor invocation uses named or default arguments, it is transformed into a block expression using the same transformation as described in (§6.6.1) . #co(){----------------------------------------------------- end-hide0} コンストラクタ呼び出しは、関数適用 x.c[targs](args1)...(argsn)です。 ここで、x は安定識別子(§3.1)であり、c は型名で、クラスを指定するかあるいは クラスのエイリアス型を定義するかのいずれかであり、targs は型引数リスト、 args1,...,argsn は引数リスト、そして与えられた引数に適用可能(§6.6)な そのクラスのコンストラクタがあるとします。 もしコンストラクタ呼び出しが、名前付きあるいはデフォルト引数を用いるときは、 (§6.6.1)中で記述したのと同じ変形を使ったブロック式に変換されます。 #co(){----------------------------------------------------- bgn-hide0} The prefix 'x.' can be omitted. A type argument list can be given only if the class c takes type parameters. Even then it can be omitted, in which case a type argument list is synthesized using local type inference (§6.26.4). If no explicit arguments are given, an empty list () is implicitly supplied . #co(){----------------------------------------------------- end-hide0} 前置子 'x.' は省略できます。 クラス c には、型パラメータをとる場合に限り、型引数リストを与えることが できます。 このときにも、それを省略できます。その場合、型引数リストはローカルな 型推論(§6.26.4)を使って合成されます。 もし明示的な引数が与えられていないなら、空リスト()が暗黙のうちに補充されます。 #co(){----------------------------------------------------- bgn-hide0} An evaluation of a constructor invocation x.c[targs](args1)...(argsn) consists of the following steps: - First, the prefix x is evaluated . - Then, the arguments args1,...,argsn are evaluated from left to right . - Finally, the class being constructed is initialized by evaluating the template of the class referred to by c . #co(){----------------------------------------------------- end-hide0} コンストラクタ呼び出し x.c[targs](args1)...(argsn)の評価は、 次のステップからなります。 - 最初に、前置子 x が評価されます。 - 次に、引数 args1,...,argsn が左から右へ評価されます。 - 最後に、構成されつつあるクラスは、c によって参照されるクラスのテンプレートを評価することで初期化されます。 &br() &br() &aname(5.1.2,option=nolink){ } *** 5.1.2 クラス線形化 (Class Linearization) #co(){----------------------------------------------------- bgn-hide0} The classes reachable through transitive closure of the direct inheritance relation from a class C are called the base classes of C . Because of mixins, the inheritance relationship on base classes forms in general a directed acyclic graph. A linearization of this graph is defined as follows . #co(){----------------------------------------------------- end-hide0} クラス C からの直接の継承関係の推移的なクロージャを通して到達可能なクラスは、 C の&italic(){基底クラス(base classes)}と呼ばれます。 ミックスインにより、基底クラス上の継承関係は一般に有向非巡回グラフになります。 このグラフの線形化は、次のように定義されています。 定義 5.1.2 : C をテンプレート C1 with ... with Cn { stats } のクラスとします。 C の線形化 LL(C)は、次のように定義されます。: #co(){----------------------------------------------------- bgn-code} LL(C) = C , LL(Cn) ⊕ ... ⊕ LL(C1) #co(){----------------------------------------------------- end-code} #co(){----------------------------------------------------- bgn-hide0} Here ⊕ denotes concatenation where elements of the right operand replace identical elements of the left operand: #co(){----------------------------------------------------- end-hide0} ここで ⊕ は連結を表し、右オペランドを左オペランドの同一の要素で置き換えます。: #co(){----------------------------------------------------- bgn-code} {a, A} ⊕ B = a,(A ⊕ B) if a ∉ B = A ⊕ B if a ∈ B #co(){----------------------------------------------------- end-code} &bold(){Example 5.1.3} : が次のクラス定義について考えます。 #co(){----------------------------------------------------- bgn-code} abstract class AbsIterator extends AnyRef { ... } trait RichIterator extends AbsIterator { ... } class StringIterator extends AbsIterator { ... } class Iter extends StringIterator with RichIterator { ... } #co(){----------------------------------------------------- end-code} クラス Iter の線形化は、次のようになります。 #co(){----------------------------------------------------- bgn-code} {Iter,RichIterator,StringIterator,AbsIterator,ScalaObject,AnyRef,Any} #co(){----------------------------------------------------- end-code} このリストの中ではトレイト ScalaObject が現れます。なぜなら、それはすべての Scala クラスに最後のミックスインとして加えられるからです (§5.1)。 クラス線形化は、継承関係を精緻化することに注意してください。: もし C が D のサブクラスなら、C と D 両方が現れるどのような線形化中でも、 C は D より先に現れます。 定義 5.1.2 は、クラス線形化が常にその直上のスーパークラスの線形化を 接尾部として含む、という特性も満たします。 例えば、StringIterator の線形化は、 #co(){----------------------------------------------------- bgn-code} { StringIterator, AbsIterator, ScalaObject, AnyRef, Any } #co(){----------------------------------------------------- end-code} です。これは、そのサブクラス Iter の線形化の接尾部となっています。 同じことはミックスインの線形化では、正しくありません。 例えば、RichIterator の線形化は次です。 #co(){----------------------------------------------------- bgn-code} { RichIterator, AbsIterator, ScalaObject, AnyRef, Any } #co(){----------------------------------------------------- end-code} これは Iter の線形化の接尾部ではありません。 &br() &br() &aname(5.1.3,option=nolink){ } *** 5.1.3 クラスメンバ (Class Members) テンプレート C1 with ... with Cn { stats } によって定義されたクラス C は、 その文並び stats の中でメンバーを定義でき、また、すべての親クラスから メンバーを継承できます。 Scala は、メソッドの静的なオーバーロードに関して、Java と C# の規則を 採用しています。 ですからクラスは、同じ名前の複数のメソッドを定義あるいは継承できます。 #co(){----------------------------------------------------- bgn-hide0} To decide whether a defined member of a class C overrides a member of a parent class, or whether the two co-exist as overloaded variants in C , Scala uses the following definition of matching on members: #co(){----------------------------------------------------- end-hide0} クラス C の定義されたメンバーがどの親クラスのメンバーをオーバライドするか、 あるいは C 中のオーバーロードされた変位指定として 2 つが共存するかどうかを 決めるために、Scala は次のメンバー&italic(){マッチング}の定義を用います。 &bold(){定義 5.1.4} : もし M と M´ が同じ名前を束縛し、下記の 1 つが 満たされるなら、メンバー定義 M はメンバー定義 M´と&italic(){マッチします}。 + M と M´のいずれもメソッド定義ではない。 + M と M´は両方とも、等価な引数型をもつ単相的なメソッドを定義する。 + M はパラメータなしのメソッドを定義し、M´ は空きのパラメータリスト()のメソッドを定義するか、あるいは&italic(){その逆}である。 + M と M´は両方とも、同数の引数型 #u(){T}、#u(){T}´ と、同数の型パラメータ #u(){t}、#u(){t}´をもつ、たとえば #u(){T}´ = [#u(){t}´/#u(){t}]#u(){T}、多相的メソッドを定義する。 メンバー定義は 2 つのカテゴリ、具象または抽象、に分けられます。 クラス C のメンバーは、&italic(){直接定義される}か(すなわち、 それらは C の文並び stats 中に現れる)、あるいは&italic(){継承された}ものです。 #co(){----------------------------------------------------- bgn-hide0} There are two rules that determine the set of members of a class, one for each category: Definition 5.1.5 A concrete member of a class C is any concrete definition M in some class Ci ∈ LL(C), except if there is a preceding class Cj ∈ LL(C) , where j < i which directly defines a concrete member M´ matching M . An abstract member of a class C is any abstract definition M in some class Ci ∈ LL(C), except if C contains already a concrete member M´ matching M , or if there is a preceding class Cj ∈ LL(C) , where j < i , which directly defines an abstract member M´ matching M . #co(){----------------------------------------------------- end-hide0} クラスのメンバーの集合を決定する 2 つの規則があり、それぞれ 1 つのカテゴリーに 対応します。 &bold(){定義 5.1.5} : クラス C の&italic(){具象メンバー}とは、あるクラス Ci∈LL(C) 中の すべての具象定義 M である。 ただしここで、M にマッチする具象メンバーM´を直接定義するような、 先行するクラス Cj∈LL(C) (j < i)がある場合を除く。 クラス C の&italic(){抽象メンバー}とは、あるクラス Ci∈LL(C) 中の すべての抽象定義 M である。 ただしここで、C がすでに M にマッチする具象メンバーM´ を含むかあるいは、 M にマッチする抽象メンバーM´を直接定義するような、先行するクラス Cj∈LL(C) (j < i)がある場合を除く。 #co(){----------------------------------------------------- bgn-hide0} This definition also determines the overriding relationships between matching members of a class C and its parents (§5.1.4). First, a concrete definition always overrides an abstract definition. Second, for definitions M and M' which are both concrete or both abstract, M overrides M´ if M appears in a class that precedes (inthe linearization of C) the class in which M´ is defined. #co(){----------------------------------------------------- end-hide0} この定義は、クラス C のマッチするメンバーとその親との間のオーバーライド関係も 決定します(§5.1.4)。 第一に、具象定義は常に抽象定義をオーバライドします。 第二に、共に具象であるか、あるいは共に抽象的な定義 M と M'について、 もし M が、M´ が定義されているクラスよりも(C の線形化で)先行するクラス中に 現れるなら、M は M´をオーバライドします。 #co(){----------------------------------------------------- bgn-hide0} It is an error if a template directly defines two matching members. It is also an error if a template contains two members (directly defined or inherited) with the same name and the same erased type (§3.7). Finally, a template is not allowed to contain two methods (directly defined or inherited) with the same name which both define default arguments. #co(){----------------------------------------------------- end-hide0} もしテンプレートが 2 つのマッチするメンバーを直接定義しているなら、エラーです。 もしテンプレートが同じ名前と同じ消去型(erased type)(§3.7)をもつ 2 つの (直接定義されたか、あるいは継承された) メンバーを含むなら、 同様にエラーです。 最後に、テンプレートは、同じ名前で共にデフォルト引数を 定義する(直接定義されたか、あるいは継承された) 2 つのメソッドを含むことは 許されていません。 &bold(){Example 5.1.6} : 次のトレイト定義について考えます。 #co(){----------------------------------------------------- bgn-code} trait A { def f: Int } trait B extends A { def f: Int = 1 ; def g: Int = 2 ; def h: Int = 3 } trait C extends A { override def f: Int = 4 ; def g: Int } trait D extends B with C { def h: Int } #co(){----------------------------------------------------- end-code} このときトレイト D は、直接定義された抽象メンバ h を持っています。 それは、トレイト B からメンバー g を、トレイト C からメンバー f を継承します。 &br() &br() &aname(5.1.4,option=nolink){ } *** 5.1.4 オーバーライド (Overriding) #co(){----------------------------------------------------- bgn-hide0} A member M of class C that matches (§5.1.3) a non-private member M´ of a base class of C is said to override that member. In this case the binding of the overriding member M must subsume (§3.5.2) the binding of the overridden member M´ . #co(){----------------------------------------------------- end-hide0} C の基底クラスの非 private なメンバー M´ にマッチ(§5.1.3)する、 クラス C のメンバー M は、そのメンバーを&italic(){オーバライド} すると言われます。 この場合、オーバーライドするメンバー M の束縛は、 オーバライドされるメンバー M´ の束縛を包含しなくてはなりません(§3.5.2)。 さらに、修飾子に関する次の制限が M および M´へ適用されます。 - M´ は final と印されていないこと。 - M は private ではないこと(§5.2)。 #co(){----------------------------------------------------- bgn-hide0} - If M is labeled private[C] for some enclosing class or package C , then M´ must be labeled private[C´] for some class or package C´ where C´ equals C or C´ is contained in C . - If M is labeled a_protected, then M´ must also be labeled a_protected. #co(){----------------------------------------------------- end-hide0} - もし M が、ある取り囲むクラス/パッケージ C について private[C] と印されているなら、M´はある取り囲むクラス/パッケージ C について private[C´] と印されていること。ただしここで、C´は C に等しいか、あるいは C´は C に含まれるものとします。 - もし M が protected と印されているなら、M´もまた protected と印されていること。 #co(){----------------------------------------------------- bgn-hide0} - If M´ is not an abstract member, then M must be labeled a_override. Furthermore , one of two possibilities must hold: -- either M is defined in a subclass of the class where is M´ is defined, -- or both M and M´ override a third member M´´ which is defined in a base class of both the classes containing M and M´ #co(){----------------------------------------------------- end-hide0} - もし M´ が抽象メンバでないなら、M は override と印されていること。さらに、次の 2 つの可能性の 1 つが満たされなくてはなりません。 -- M は、M´ が定義されているクラスのサブクラス内で定義されているか、あるいは -- M と M´ の両方とも、M や M´ を含む両クラスの (1 つの)基底クラス内で定義されている、第 3 のメンバー M´´をオーバライドする。 #co(){----------------------------------------------------- bgn-hide0} - If M´ is incomplete (§5.2) in C then M must be labeled abstract_override . - If M and M´ are both concrete value definitions, then either none of them is marked lazy or both must be marked lazy . #co(){----------------------------------------------------- end-hide0} - もし M´が C 中で不完全(incomplete §5.2)なら、M は abstract override と印されなていること。 - もし M と M´が両方とも具象値定義なら、そのどちらも lazy と印されないか、あるいは両方とも lazy と印されるかのどちらかであること。 パラメータなしのメソッドに関係する特別の規則があります。 もし def f : T = ... あるいは def f = ... として定義されたパラメータなしの メソッドが、空きのパラメータリストをもつ、型 ()T´のメソッドをオーバライド するなら、f も同じく空きのパラメータリストを持つと想定されます。 もう 1 つの制限が抽象型メンバーに適用されます。: その上限境界として volatile 型(§3.6)をもつ抽象型メンバーは、 volatile 型の上限境界をもたない抽象型メンバーをオーバライドできません。 オーバーライドするメソッドは、スーパークラス中の定義からすべての デフォルト引数を継承します。 #co(){----------------------------------------------------- bgn-hide0} By specifying default arguments in the overriding method it is possible to add new defaults (if the corresponding parameter in the superclass does not have a default) or to override the defaults of the superclass (otherwise) . #co(){----------------------------------------------------- end-hide0} オーバーライドするメソッド中でデフォルト引数を指定して、(もしスーパークラス中の対応するパラメータがデフォルトを持たないなら)新しいデフォルトを追加したり、 あるいは(そうでなければ)、スーパークラスのデフォルトをオーバライドできます。 &bold(){Example 5.1.7} : 次の定義を考えます。 #co(){----------------------------------------------------- bgn-code} trait Root { type T <: Root } trait A extends Root { type T <: A } trait B extends Root { type T <: B } trait C extends A with B #co(){----------------------------------------------------- end-code} このとき、クラス定義 C は正しい形ではありません。なぜなら、C 中の T の束縛は type T <: B であり、型 A 中の T の束縛 type T <: A の包含に失敗するからです。 この問題は、クラス C 中に型 T のオーバーライド定義を加えることで、解決できます: #co(){----------------------------------------------------- bgn-code} class C extends A with B { type T <: C } #co(){----------------------------------------------------- end-code} &br() &br() &aname(5.1.5,option=nolink){ } *** 5.1.5 継承クロージャ (Inheritance Closure) #co(){----------------------------------------------------- bgn-hide0} Let C be a class type. The inheritance closure of C is the smallest set SS of types such that - If T is in SS , then every type T´ which forms syntactically a part of T is also in SS . - If T is a class type in SS , then all parents (§5.1) of T are also in SS . It is a static error if the inheritance closure of a class type consists of an infinite number of types. (This restriction is necessary to make subtyping decidable [KP07]). #co(){----------------------------------------------------- end-hide0} C はクラス型であるとします。 C の&italic(){継承クロージャ(inheritance closure)}とは、 次のような型の最小の集合 SS です。 - もし T が SS 中にあれば、T の一部を文法的に形成するすべての型 T´もまた SS 中にある。 - もし T が SS 中のクラス型なら、T のすべての親(§5.1)は同じく SS 中にある。 もしクラス型の継承クロージャが無数の型からなるなら、静的エラーです (この制限は、サブ型付けを決定可能とするために必要です[KP07] )。 &br() &br() &aname(5.1.6,option=nolink){ } *** 5.1.6 事前定義 (Early Definitions) &bold(){構文:} #co(){----------------------------------------------------- bgn-code} EarlyDefs ::= '{' [EarlyDef {semi EarlyDef}] '}' 'with' EarlyDef ::= {Annotation} {Modifier} PatVarDef #co(){----------------------------------------------------- end-code} #co(){----------------------------------------------------- bgn-hide0} A template may start with an early field definition clause, which serves to define certain field values before the supertype constructor is called. #co(){----------------------------------------------------- end-hide0} テンプレートを&italic(){事前フィールド定義(early field definition)}節 で始めることができ、それは、スーパー型のコンストラクタがコールされる前に、 ある特定のフィールド値を定義するのに役立ちます。 テンプレート { val p1 : T1 = e1 ... val pn : Tn = en } with sc with mt1 with mtn {stats} #co(){----------------------------------------------------- bgn-hide0} The initial pattern definitions of p1,...,pn are called early definitions. They define fields which form part of the template. Every early definition must define at least one variable. #co(){----------------------------------------------------- end-hide0} 中の、最初のパターン定義 p1,...,pn は&italic(){事前定義(early difinition)} と呼ばれます。 それらはテンプレートの一部をなすフィールドを定義します。 すべての事前定義は、少なくとも 1 つの変数を定義しなくてはなりません。 #co(){----------------------------------------------------- bgn-hide0} An early definition is type-checked and evaluated in the scope which is in effect just before the template being defined, augmented by any type parameters of the enclosing class and by any early definitions preceding the one being defined. In particular, any reference to this in the right-hand side of an early definition refers to the identity of this just outside the template. #co(){----------------------------------------------------- end-hide0} 事前定義は型チェックされ、そのテンプレートが定義される直前に有効なスコープ中で 評価されます。 また、取り囲むクラスのすべての型パラメータと、 定義しているものに先行するすべての事前定義によって拡張されます。 特に、事前定義の右辺における this への参照はすべて、テンプレートのすぐ外の this 識別子への参照です。 #co(){----------------------------------------------------- bgn-hide0} Consequently, it is impossible that an early definition refers to the object being constructed by the template, or refers to one of its fields and methods, except for any other preceding early definition in the same section. Furthermore, references to preceding early definitions always refer to the value that's defined there, and do not take into account overriding definitions . #co(){----------------------------------------------------- end-hide0} したがって、事前定義がテンプレートによって構築中のオブジェクトを参照したり、 あるいは、同じセクション中の先行する他の事前定義以外の、フィールドや メソッドの 1 つを参照することはできません。 さらに、先行する事前定義への参照は、そこで定義されている値を常に参照し、 オーバーライド定義は考慮されません。 #co(){----------------------------------------------------- bgn-hide0} In other words, a block of early definitions is evaluated exactly as if it was a local bock containing a number of value definitions . Early definitions are evaluated in the order they are being defined before the superclass constructor of the template is called . #co(){----------------------------------------------------- end-hide0} 言い換えると、事前定義ブロックは、まさに、複数の値定義を含むローカルなブロック であるかのように評価されます。 事前定義は、テンプレートのスーパークラスコンストラクタが呼ばれる前に、 それらが定義された順番で評価されます。 &bold(){Example 5.1.8} : 事前定義は、通常のコンストラクタ・パラメータをもたないトレイトに対して 特に役立ちます。 例: #co(){----------------------------------------------------- bgn-code} trait Greeting { val name: String val msg = "How are you, "+name } class C extends { val name = "Bob" } with Greeting { println(msg) } #co(){----------------------------------------------------- end-code} 上記のコードで、フィールド name は Greeting のコンストラクタが呼び出される前に 初期化されます。 ですから、クラス Greeting 中のフィールド msg は "How are you, Bob" に適切に初期化されます。 #co(){----------------------------------------------------- bgn-hide0} If name had been initialized instead in C's normal class body, it would be initialized after the constructor of Greeting. In that case, msg would be initialized to "How are you, <null>" . #co(){----------------------------------------------------- end-hide0} 代わりに、もし name が C の通常のクラス本体中で初期化されるなら、 それは Greeing のコンストラクタの後に初期化されます。 その場合、msg は "How are you, <null>" と初期化されるでしょう。 #center(){[[前ページ>Spec2.8Chap4b]]  [[目次>Spec2.8和訳]] [[次ページ>Spec2.8Chap5b]]}
* 第 5 章 クラスとオブジェクト &bold(){構文:} #co(){----------------------------------------------------- bgn-code} TmplDef ::= ['case'] 'class' ClassDef | ['case'] 'object' ObjectDef | 'trait' TraitDef #co(){----------------------------------------------------- end-code} #co(){----------------------------------------------------- bgn-hide0} Classes (§5.3) and objects (§5.4) are both defined in terms of templates . #co(){----------------------------------------------------- end-hide0} クラス(§5.3)とオブジェクト(§5.4)は共にテンプレートの観点で定義されています。 &br() &br() &aname(5.1,option=nolink){ } ** 5.1 テンプレート (Templates) &bold(){構文:} #co(){----------------------------------------------------- bgn-code} ClassTemplate ::= [EarlyDefs] ClassParents [TemplateBody] TraitTemplate ::= [EarlyDefs] TraitParents [TemplateBody] ClassParents ::= Constr {'with' AnnotType} TraitParents ::= AnnotType {'with' AnnotType} TemplateBody ::= [nl] '{' [SelfType] TemplateStat {semi TemplateStat} '}' SelfType ::= id [':' Type] '=>' | this ':' Type '=>' #co(){----------------------------------------------------- end-code} #co(){----------------------------------------------------- bgn-hide0} A template defines the type signature, behavior and initial state of a trait or class of objects or of a single object. Templates form part of instance creation expressions, class definitions, and object definitions. A template sc with mt1 with ... with mtn {stats} consists of a constructor invocation sc which defines the template's superclass, trait references mt1,...,mtn (n >= 0), which define the template's traits, and a statement sequence stats which contains initialization code and additional member definitions for the template. #co(){----------------------------------------------------- end-hide0} テンプレートは、クラス/トレイトあるいはオブジェクトあるいは シングルオブジェクト(訳注:シングルトンオブジェクトのこと?)の、 型シグニチャ、振る舞い、初期状態を定義します。 テンプレートは、 インスタンス生成式、クラス定義とオブジェクト定義等を形づくります。 テンプレート sc with mt1 with ... with mtn {stats} は、テンプレートの &italic(){スーパークラス}を定義するコンストラクタ呼び出し sc、 テンプレートの&italic(){トレイト}を定義するトレイト参照 mt1,...,mtn (n >= 0)、テンプレートの初期化コードと 追加のメンバー定義を含む文並び stats、からなります。 各トレイト参照 mti は、トレイト(§5.3.3)を表わします。 これと対照して、スーパークラスコンストラクタ sc は通常、トレイトではない クラスを参照します。 #co(){----------------------------------------------------- bgn-hide0} It is possible to write a list of parents that starts with a trait reference, e.g. mt1 with ... with mtn . In that case the list of parents is implicitly extended to include the supertype of mt1 as first parent type. The new supertype must have at least one constructor that does not take parameters. In the following, we will always assume that this implicit extension has been performed, so that the first parent class of a template is a regular superclass constructor, not a trait reference . #co(){----------------------------------------------------- end-hide0} トレイト参照で始まる親のリストを書くことが可能です。例えば、 mt1 with ... with mtn。 この場合、親のリストは、最初の親型として mt1 の スーパー型を含むように暗黙のうちに展開されます。 新しいスーパー型は、パラメータをとらない少なくとも 1 つのコンストラクタを 持っていなくてはなりません。 以降では、常にこの暗黙の展開が実行されると 想定します。ですから、テンプレートの最初の親クラスは、通常のスーパークラス コンストラクタであり、トレイト参照ではありません。 #co(){----------------------------------------------------- bgn-hide0} The list of parents of every class is also always implicitly extended by a reference to the scala.ScalaObject trait as last mixin. E.g. sc with mt1 with ... with mtn {stats } becomes mt1 with ... with mtn {stats } with ScalaObject {stats } . #co(){----------------------------------------------------- end-hide0} すべてのクラスの親のリストは同様に、最後のミックスインである scala.ScalaObject トレイトへの参照により、常に暗黙のうちに拡張されます。 つまり、 #co(){----------------------------------------------------- bgn-code} sc with mt1 with ... with mtn {stats } #co(){----------------------------------------------------- end-code} は、次になります。 #co(){----------------------------------------------------- bgn-code} mt1 with ... with mtn {stats } with ScalaObject {stats} #co(){----------------------------------------------------- end-code} テンプレートの親のリストは、正しい形でなければなりません。 #co(){----------------------------------------------------- bgn-hide0} This means that the class denoted by the superclass constructor sc must be a subclass of the superclasses of all the traits mt1,...,mtn . In other words, the non-trait classes inherited by a template form a chain in the inheritance hierarchy which starts with the template's superclass . #co(){----------------------------------------------------- end-hide0} これはスーパークラスコンストラクタ sc によって表されるクラスが、 すべてのトレイト mt1,...,mtn のスーパークラスのサブクラスでなければ ならないことを意味します。 言い換えれば、テンプレートによって継承される非トレイトクラスは、テンプレートの スーパークラスで始まる、継承階層の中で 1 つのチェインを形成します。 #co(){----------------------------------------------------- bgn-hide0} The least proper supertype of a template is the class type or compound type (§3.2.7) consisting of all its parent class types . #co(){----------------------------------------------------- end-hide0} テンプレートの&italic(){最小固有のスーパー型(least proper supertype)}とは、 そのすべての親クラス型から構成される複合型(§3.2.7)あるいはクラス型です。 #co(){----------------------------------------------------- bgn-hide0} The statement sequence stats contains member definitions that define new members or overwrite members in the parent classes. If the template forms part of an abstract class or trait definition, the statement part stats may also contain declarations of abstract members. If the template forms part of a concrete class definition, stats may still contain declarations of abstract type members, but not of abstract term members. Furthermore, stats may in any case also contain expressions; these are executed in the order they are given as part of the initialization of a template . #co(){----------------------------------------------------- end-hide0} 文並び stats は、新しいメンバーを定義するメンバー定義、あるいは 親クラス中のメンバーを上書きするメンバー定義を含みます。 もしテンプレートが抽象クラスあるいはトレイト定義を形づくるなら、文部分 stats も抽象メンバ宣言を含んでいて構いません。 もしテンプレートが具象クラス定義を形づくるなら、stats はそれでも、 抽象型メンバの宣言を含んでいても構いません。ただし、抽象項メンバの宣言は 含みません。 さらに、stats は、いずれの場合も式を含み得ます。; それらはテンプレートの初期化の一部として与えられた順に実行されます。 #co(){----------------------------------------------------- bgn-hide0} The sequence of template statements may be prefixed with a formal parameter definition and an arrow, e.g. x =>, or x :T =>. If a formal parameter is given, it can be used as an alias for the reference this throughout the body of the template. #co(){----------------------------------------------------- end-hide0} テンプレート文の並びには、形式上のパラメータ定義と矢印、たとえば、 x => あるいは x :T => 、が前につくことがあります。 もし形式上のパラメータが与えられていれば、それをテンプレート本体全体にわたって this 参照のエイリアスとして使えます。 #co(){----------------------------------------------------- bgn-hide0} If the formal parameter comes with a type T , this definition affects the self type S of the underlying class or object as follows: Let C be the type of the class or trait or object defining the template. If a type T is given for the formal self parameter, S is the greatest lower bound of T and C . If no type T is given, S is just C . Inside the template, the type of this is assumed to be S . #co(){----------------------------------------------------- end-hide0} もし形式上のパラメータが型 T と共にあるなら、その定義は、下地となっている クラス/オブジェクトの&italic(){自己型} S に次のような影響を与えます。: まず、C をテンプレートを定義するクラス/トレイト/オブジェクトの型であると 仮定します。 もし型 T が形式上の自己パラメータに対して与えられているなら、S は T と C の 最大の下限境界です。 もし型 T が与えられていないなら、S はたんに C です。 テンプレート中では、this の型は S であると想定されます。 #co(){----------------------------------------------------- bgn-hide0} The self type of a class or object must conform to the self types of all classes which are inherited by the template t . A second form of self type annotation reads just this: S =>. It prescribes the type S for this without introducing an alias name for it . #co(){----------------------------------------------------- end-hide0} クラスあるいはオブジェクトの自己型は、テンプレート t によって継承される すべてのクラスの自己型に適合しなくてはなりません。 自己型アノテーションの 2 つめの形は、たんに this: S => と書きます。 これにより、エイリアス名を導入せずに this の型 S を記述できます。 &bold(){Example 5.1.1} : 次のクラス定義を考えてください: #co(){----------------------------------------------------- bgn-code} class Base extends Object {} trait Mixin extends Base {} object O extends Mixin {} #co(){----------------------------------------------------- end-code} この場合、O の定義は次のように展開されます。 #co(){----------------------------------------------------- bgn-code} object O extends Base with Mixin {} #co(){----------------------------------------------------- end-code} &bold(){Java 型からの継承 :} テンプレートは、そのスーパークラスとして Java クラスを、 そのミックスインとして Java インターフェースを持っていても構いません。 &bold(){テンプレートの評価 :} #co(){----------------------------------------------------- bgn-hide0} Consider a template sc with mt1 with mtn {stats } . If this is the template of a trait (§5.3.3) then its mixin-evaluation consists of an evaluation of the statement sequence stats . #co(){----------------------------------------------------- end-hide0} テンプレート sc with mt1 mtn {stats } について考えます。 もしこれがトレイト(§5.3.3)のテンプレートなら、 その&italic(){ミックスイン評価}は、文並び stats の &italic(){評価}から構成されます。 #co(){----------------------------------------------------- bgn-hide0} If this is not a template of a trait, then its evaluation consists of the following steps . - First, the superclass constructor sc is evaluated (§5.1.1) . - Then, all base classes in the template's linearization (§5.1.2) up to the template's superclass denoted by sc are mixin-evaluated. Mixin-evaluation happens in reverse order of occurrence in the linearization . - Finally the statement sequence stats is evaluated . #co(){----------------------------------------------------- end-hide0} もしこれがトレイトのテンプレートでないなら、その評価は、 次のステップによって構成されます。 - 最初に、スーパークラスコンストラクタ sc が評価されます(§5.1.1)。 - 次に、sc によって表わわれるテンプレートのスーパークラスに至る、テンプレート線形化(§5.1.2)中のすべての基底クラスはミックスイン評価されます。ミックスイン評価は、線形化中での出現の逆順でされます。 - 最後に文並び stats が評価されます。 &br() &br() &aname(5.1.1,option=nolink){ } *** 5.1.1 コンストラクタ呼び出し (Constructor Invocations) &bold(){構文:} #co(){----------------------------------------------------- bgn-code} Constr ::= AnnotType {'(' [Exprs] ')'} #co(){----------------------------------------------------- end-code} #co(){----------------------------------------------------- bgn-hide0} Constructor invocations define the type, members, and initial state of objects created by an instance creation expression, or of parts of an object's definition which are inherited by a class or object definition. #co(){----------------------------------------------------- end-hide0} コンストラクタ呼び出しは、型、メンバー、そしてインスタンス生成式によって 生成されるオブジェクトの初期状態、あるいはクラス/オブジェクト定義によって 継承されたオブジェクト定義部分の初期状態等を定義します。 #co(){----------------------------------------------------- bgn-hide0} A constructor invocation is a function application x.c[targs](args1)...(argsn) , where x is a stable identifier (§3.1), c is a type name which either designates a class or defines an alias type for one, targs is a type argument list, args1,...,argsn are argument lists, and there is a constructor of that class which is applicable (§6.6) to the given arguments. If the constructor invocation uses named or default arguments, it is transformed into a block expression using the same transformation as described in (§6.6.1) . #co(){----------------------------------------------------- end-hide0} コンストラクタ呼び出しは、関数適用 x.c[targs](args1)...(argsn)です。 ここで、x は安定識別子(§3.1)であり、c は型名で、クラスを指定するかあるいは クラスのエイリアス型を定義するかのいずれかであり、targs は型引数リスト、 args1,...,argsn は引数リスト、そして与えられた引数に適用可能(§6.6)な そのクラスのコンストラクタがあるとします。 もしコンストラクタ呼び出しが、名前付きあるいはデフォルト引数を用いるときは、 (§6.6.1)中で記述したのと同じ変形を使ったブロック式に変換されます。 #co(){----------------------------------------------------- bgn-hide0} The prefix 'x.' can be omitted. A type argument list can be given only if the class c takes type parameters. Even then it can be omitted, in which case a type argument list is synthesized using local type inference (§6.26.4). If no explicit arguments are given, an empty list () is implicitly supplied . #co(){----------------------------------------------------- end-hide0} 前置子 'x.' は省略できます。 クラス c には、型パラメータをとる場合に限り、型引数リストを与えることが できます。 このときにも、それを省略できます。その場合、型引数リストはローカルな 型推論(§6.26.4)を使って合成されます。 もし明示的な引数が与えられていないなら、空リスト()が暗黙のうちに補充されます。 #co(){----------------------------------------------------- bgn-hide0} An evaluation of a constructor invocation x.c[targs](args1)...(argsn) consists of the following steps: - First, the prefix x is evaluated . - Then, the arguments args1,...,argsn are evaluated from left to right . - Finally, the class being constructed is initialized by evaluating the template of the class referred to by c . #co(){----------------------------------------------------- end-hide0} コンストラクタ呼び出し x.c[targs](args1)...(argsn)の評価は、 次のステップからなります。 - 最初に、前置子 x が評価されます。 - 次に、引数 args1,...,argsn が左から右へ評価されます。 - 最後に、構成されつつあるクラスは、c によって参照されるクラスのテンプレートを評価することで初期化されます。 &br() &br() &aname(5.1.2,option=nolink){ } *** 5.1.2 クラス線形化 (Class Linearization) #co(){----------------------------------------------------- bgn-hide0} The classes reachable through transitive closure of the direct inheritance relation from a class C are called the base classes of C . Because of mixins, the inheritance relationship on base classes forms in general a directed acyclic graph. A linearization of this graph is defined as follows . #co(){----------------------------------------------------- end-hide0} クラス C からの直接の継承関係の推移的なクロージャを通して到達可能なクラスは、 C の&italic(){基底クラス(base classes)}と呼ばれます。 ミックスインにより、基底クラス上の継承関係は一般に有向非巡回グラフになります。 このグラフの線形化は、次のように定義されています。 定義 5.1.2 : C をテンプレート C1 with ... with Cn { stats } のクラスとします。 C の線形化 LL(C)は、次のように定義されます。: #co(){----------------------------------------------------- bgn-code} LL(C) = C , LL(Cn) ⊕ ... ⊕ LL(C1) #co(){----------------------------------------------------- end-code} #co(){----------------------------------------------------- bgn-hide0} Here ⊕ denotes concatenation where elements of the right operand replace identical elements of the left operand: #co(){----------------------------------------------------- end-hide0} ここで ⊕ は連結を表し、右オペランドを左オペランドの同一の要素で置き換えます。: #co(){----------------------------------------------------- bgn-code} {a, A} ⊕ B = a,(A ⊕ B) if a ∉ B = A ⊕ B if a ∈ B #co(){----------------------------------------------------- end-code} &bold(){Example 5.1.3} : が次のクラス定義について考えます。 #co(){----------------------------------------------------- bgn-code} abstract class AbsIterator extends AnyRef { ... } trait RichIterator extends AbsIterator { ... } class StringIterator extends AbsIterator { ... } class Iter extends StringIterator with RichIterator { ... } #co(){----------------------------------------------------- end-code} クラス Iter の線形化は、次のようになります。 #co(){----------------------------------------------------- bgn-code} {Iter,RichIterator,StringIterator,AbsIterator,ScalaObject,AnyRef,Any} #co(){----------------------------------------------------- end-code} このリストの中ではトレイト ScalaObject が現れます。なぜなら、それはすべての Scala クラスに最後のミックスインとして加えられるからです (§5.1)。 クラス線形化は、継承関係を精緻化することに注意してください。: もし C が D のサブクラスなら、C と D 両方が現れるどのような線形化中でも、 C は D より先に現れます。 定義 5.1.2 は、クラス線形化が常にその直上のスーパークラスの線形化を 接尾部として含む、という特性も満たします。 例えば、StringIterator の線形化は、 #co(){----------------------------------------------------- bgn-code} { StringIterator, AbsIterator, ScalaObject, AnyRef, Any } #co(){----------------------------------------------------- end-code} です。これは、そのサブクラス Iter の線形化の接尾部となっています。 同じことはミックスインの線形化では、正しくありません。 例えば、RichIterator の線形化は次です。 #co(){----------------------------------------------------- bgn-code} { RichIterator, AbsIterator, ScalaObject, AnyRef, Any } #co(){----------------------------------------------------- end-code} これは Iter の線形化の接尾部ではありません。 &br() &br() &aname(5.1.3,option=nolink){ } *** 5.1.3 クラスメンバ (Class Members) テンプレート C1 with ... with Cn { stats } によって定義されたクラス C は、 その文並び stats の中でメンバーを定義でき、また、すべての親クラスから メンバーを継承できます。 Scala は、メソッドの静的なオーバーロードに関して、Java と C# の規則を 採用しています。 ですからクラスは、同じ名前の複数のメソッドを定義あるいは継承できます。 #co(){----------------------------------------------------- bgn-hide0} To decide whether a defined member of a class C overrides a member of a parent class, or whether the two co-exist as overloaded variants in C , Scala uses the following definition of matching on members: #co(){----------------------------------------------------- end-hide0} クラス C の定義されたメンバーがどの親クラスのメンバーをオーバライドするか、 あるいは C 中のオーバーロードされた変位指定として 2 つが共存するかどうかを 決めるために、Scala は次のメンバー&italic(){マッチング}の定義を用います。 &bold(){定義 5.1.4} : もし M と M´ が同じ名前を束縛し、下記の 1 つが 満たされるなら、メンバー定義 M はメンバー定義 M´と&italic(){マッチします}。 + M と M´のいずれもメソッド定義ではない。 + M と M´は両方とも、等価な引数型をもつ単相的なメソッドを定義する。 + M はパラメータなしのメソッドを定義し、M´ は空きのパラメータリスト()のメソッドを定義するか、あるいは&italic(){その逆}である。 + M と M´は両方とも、同数の引数型 #u(){T}、#u(){T}´ と、同数の型パラメータ #u(){t}、#u(){t}´をもつ、たとえば #u(){T}´ = [#u(){t}´/#u(){t}]#u(){T}、多相的メソッドを定義する。 メンバー定義は 2 つのカテゴリ、具象または抽象、に分けられます。 クラス C のメンバーは、&italic(){直接定義される}か(すなわち、 それらは C の文並び stats 中に現れる)、あるいは&italic(){継承された}ものです。 #co(){----------------------------------------------------- bgn-hide0} There are two rules that determine the set of members of a class, one for each category: Definition 5.1.5 A concrete member of a class C is any concrete definition M in some class Ci ∈ LL(C), except if there is a preceding class Cj ∈ LL(C) , where j < i which directly defines a concrete member M´ matching M . An abstract member of a class C is any abstract definition M in some class Ci ∈ LL(C), except if C contains already a concrete member M´ matching M , or if there is a preceding class Cj ∈ LL(C) , where j < i , which directly defines an abstract member M´ matching M . #co(){----------------------------------------------------- end-hide0} クラスのメンバーの集合を決定する 2 つの規則があり、それぞれ 1 つのカテゴリーに 対応します。 &bold(){定義 5.1.5} : クラス C の&italic(){具象メンバー}とは、あるクラス Ci∈LL(C) 中の すべての具象定義 M である。 ただしここで、M にマッチする具象メンバーM´を直接定義するような、 先行するクラス Cj∈LL(C) (j < i)がある場合を除く。 クラス C の&italic(){抽象メンバー}とは、あるクラス Ci∈LL(C) 中の すべての抽象定義 M である。 ただしここで、C がすでに M にマッチする具象メンバーM´ を含むかあるいは、 M にマッチする抽象メンバーM´を直接定義するような、先行するクラス Cj∈LL(C) (j < i)がある場合を除く。 #co(){----------------------------------------------------- bgn-hide0} This definition also determines the overriding relationships between matching members of a class C and its parents (§5.1.4). First, a concrete definition always overrides an abstract definition. Second, for definitions M and M' which are both concrete or both abstract, M overrides M´ if M appears in a class that precedes (inthe linearization of C) the class in which M´ is defined. #co(){----------------------------------------------------- end-hide0} この定義は、クラス C のマッチするメンバーとその親との間のオーバーライド関係も 決定します(§5.1.4)。 第一に、具象定義は常に抽象定義をオーバライドします。 第二に、共に具象であるか、あるいは共に抽象的な定義 M と M'について、 もし M が、M´ が定義されているクラスよりも(C の線形化で)先行するクラス中に 現れるなら、M は M´をオーバライドします。 #co(){----------------------------------------------------- bgn-hide0} It is an error if a template directly defines two matching members. It is also an error if a template contains two members (directly defined or inherited) with the same name and the same erased type (§3.7). Finally, a template is not allowed to contain two methods (directly defined or inherited) with the same name which both define default arguments. #co(){----------------------------------------------------- end-hide0} もしテンプレートが 2 つのマッチするメンバーを直接定義しているなら、エラーです。 もしテンプレートが同じ名前と同じ消去型(erased type)(§3.7)をもつ 2 つの (直接定義されたか、あるいは継承された) メンバーを含むなら、 同様にエラーです。 最後に、テンプレートは、同じ名前で共にデフォルト引数を 定義する(直接定義されたか、あるいは継承された) 2 つのメソッドを含むことは 許されていません。 &bold(){Example 5.1.6} : 次のトレイト定義について考えます。 #co(){----------------------------------------------------- bgn-code} trait A { def f: Int } trait B extends A { def f: Int = 1 ; def g: Int = 2 ; def h: Int = 3 } trait C extends A { override def f: Int = 4 ; def g: Int } trait D extends B with C { def h: Int } #co(){----------------------------------------------------- end-code} このときトレイト D は、直接定義された抽象メンバ h を持っています。 それは、トレイト B からメンバー g を、トレイト C からメンバー f を継承します。 &br() &br() &aname(5.1.4,option=nolink){ } *** 5.1.4 オーバーライド (Overriding) #co(){----------------------------------------------------- bgn-hide0} A member M of class C that matches (§5.1.3) a non-private member M´ of a base class of C is said to override that member. In this case the binding of the overriding member M must subsume (§3.5.2) the binding of the overridden member M´ . #co(){----------------------------------------------------- end-hide0} C の基底クラスの非 private なメンバー M´ にマッチ(§5.1.3)する、 クラス C のメンバー M は、そのメンバーを&italic(){オーバライド} すると言われます。 この場合、オーバーライドするメンバー M の束縛は、 オーバライドされるメンバー M´ の束縛を包含しなくてはなりません(§3.5.2)。 さらに、修飾子に関する次の制限が M および M´へ適用されます。 - M´ は final と印されていないこと。 - M は private ではないこと(§5.2)。 #co(){----------------------------------------------------- bgn-hide0} - If M is labeled private[C] for some enclosing class or package C , then M´ must be labeled private[C´] for some class or package C´ where C´ equals C or C´ is contained in C . - If M is labeled a_protected, then M´ must also be labeled a_protected. #co(){----------------------------------------------------- end-hide0} - もし M が、ある取り囲むクラス/パッケージ C について private[C] と印されているなら、M´はある取り囲むクラス/パッケージ C について private[C´] と印されていること。ただしここで、C´は C に等しいか、あるいは C´は C に含まれるものとします。 - もし M が protected と印されているなら、M´もまた protected と印されていること。 #co(){----------------------------------------------------- bgn-hide0} - If M´ is not an abstract member, then M must be labeled a_override. Furthermore , one of two possibilities must hold: -- either M is defined in a subclass of the class where is M´ is defined, -- or both M and M´ override a third member M´´ which is defined in a base class of both the classes containing M and M´ #co(){----------------------------------------------------- end-hide0} - もし M´ が抽象メンバでないなら、M は override と印されていること。さらに、次の 2 つの可能性の 1 つが満たされなくてはなりません。 -- M は、M´ が定義されているクラスのサブクラス内で定義されているか、あるいは -- M と M´ の両方とも、M や M´ を含む両クラスの (1 つの)基底クラス内で定義されている、第 3 のメンバー M´´をオーバライドする。 #co(){----------------------------------------------------- bgn-hide0} - If M´ is incomplete (§5.2) in C then M must be labeled abstract_override . - If M and M´ are both concrete value definitions, then either none of them is marked lazy or both must be marked lazy . #co(){----------------------------------------------------- end-hide0} - もし M´が C 中で不完全(incomplete §5.2)なら、M は abstract override と印されなていること。 - もし M と M´が両方とも具象値定義なら、そのどちらも lazy と印されないか、あるいは両方とも lazy と印されるかのどちらかであること。 パラメータなしのメソッドに関係する特別の規則があります。 もし def f : T = ... あるいは def f = ... として定義されたパラメータなしの メソッドが、空きのパラメータリストをもつ、型 ()T´のメソッドをオーバライド するなら、f も同じく空きのパラメータリストを持つと想定されます。 もう 1 つの制限が抽象型メンバーに適用されます。: その上限境界として volatile 型(§3.6)をもつ抽象型メンバーは、 volatile 型の上限境界をもたない抽象型メンバーをオーバライドできません。 オーバーライドするメソッドは、スーパークラス中の定義からすべての デフォルト引数を継承します。 #co(){----------------------------------------------------- bgn-hide0} By specifying default arguments in the overriding method it is possible to add new defaults (if the corresponding parameter in the superclass does not have a default) or to override the defaults of the superclass (otherwise) . #co(){----------------------------------------------------- end-hide0} オーバーライドするメソッド中でデフォルト引数を指定して、(もしスーパークラス中の対応するパラメータがデフォルトを持たないなら)新しいデフォルトを追加したり、 あるいは(そうでなければ)、スーパークラスのデフォルトをオーバライドできます。 &bold(){Example 5.1.7} : 次の定義を考えます。 #co(){----------------------------------------------------- bgn-code} trait Root { type T <: Root } trait A extends Root { type T <: A } trait B extends Root { type T <: B } trait C extends A with B #co(){----------------------------------------------------- end-code} このとき、クラス定義 C は正しい形ではありません。なぜなら、C 中の T の束縛は type T <: B であり、型 A 中の T の束縛 type T <: A の包含に失敗するからです。 この問題は、クラス C 中に型 T のオーバーライド定義を加えることで、解決できます: #co(){----------------------------------------------------- bgn-code} class C extends A with B { type T <: C } #co(){----------------------------------------------------- end-code} &br() &br() &aname(5.1.5,option=nolink){ } *** 5.1.5 継承クロージャ (Inheritance Closure) #co(){----------------------------------------------------- bgn-hide0} Let C be a class type. The inheritance closure of C is the smallest set SS of types such that - If T is in SS , then every type T´ which forms syntactically a part of T is also in SS . - If T is a class type in SS , then all parents (§5.1) of T are also in SS . It is a static error if the inheritance closure of a class type consists of an infinite number of types. (This restriction is necessary to make subtyping decidable [KP07]). #co(){----------------------------------------------------- end-hide0} C はクラス型であるとします。 C の&italic(){継承クロージャ(inheritance closure)}とは、 次のような型の最小の集合 SS です。 - もし T が SS 中にあれば、T の一部を文法的に形成するすべての型 T´もまた SS 中にある。 - もし T が SS 中のクラス型なら、T のすべての親(§5.1)は同じく SS 中にある。 もしクラス型の継承クロージャが無数の型からなるなら、静的エラーです (この制限は、サブ型付けを決定可能とするために必要です[KP07] )。 &br() &br() &aname(5.1.6,option=nolink){ } *** 5.1.6 事前定義 (Early Definitions) &bold(){構文:} #co(){----------------------------------------------------- bgn-code} EarlyDefs ::= '{' [EarlyDef {semi EarlyDef}] '}' 'with' EarlyDef ::= {Annotation} {Modifier} PatVarDef #co(){----------------------------------------------------- end-code} #co(){----------------------------------------------------- bgn-hide0} A template may start with an early field definition clause, which serves to define certain field values before the supertype constructor is called. #co(){----------------------------------------------------- end-hide0} テンプレートを&italic(){事前フィールド定義(early field definition)}節 で始めることができ、それは、スーパー型のコンストラクタがコールされる前に、 ある特定のフィールド値を定義するのに役立ちます。 テンプレート { val p1 : T1 = e1 ... val pn : Tn = en } with sc with mt1 with mtn {stats} #co(){----------------------------------------------------- bgn-hide0} The initial pattern definitions of p1,...,pn are called early definitions. They define fields which form part of the template. Every early definition must define at least one variable. #co(){----------------------------------------------------- end-hide0} 中の、最初のパターン定義 p1,...,pn は&italic(){事前定義(early difinition)} と呼ばれます。 それらはテンプレートの一部をなすフィールドを定義します。 すべての事前定義は、少なくとも 1 つの変数を定義しなくてはなりません。 #co(){----------------------------------------------------- bgn-hide0} An early definition is type-checked and evaluated in the scope which is in effect just before the template being defined, augmented by any type parameters of the enclosing class and by any early definitions preceding the one being defined. In particular, any reference to this in the right-hand side of an early definition refers to the identity of this just outside the template. #co(){----------------------------------------------------- end-hide0} 事前定義は型チェックされ、そのテンプレートが定義される直前に有効なスコープ中で 評価されます。 また、取り囲むクラスのすべての型パラメータと、 定義しているものに先行するすべての事前定義によって拡張されます。 特に、事前定義の右辺における this への参照はすべて、テンプレートのすぐ外の this 識別子への参照です。 #co(){----------------------------------------------------- bgn-hide0} Consequently, it is impossible that an early definition refers to the object being constructed by the template, or refers to one of its fields and methods, except for any other preceding early definition in the same section. Furthermore, references to preceding early definitions always refer to the value that's defined there, and do not take into account overriding definitions . #co(){----------------------------------------------------- end-hide0} したがって、事前定義がテンプレートによって構築中のオブジェクトを参照したり、 あるいは、同じセクション中の先行する他の事前定義以外の、フィールドや メソッドの 1 つを参照することはできません。 さらに、先行する事前定義への参照は、そこで定義されている値を常に参照し、 オーバーライド定義は考慮されません。 #co(){----------------------------------------------------- bgn-hide0} In other words, a block of early definitions is evaluated exactly as if it was a local bock containing a number of value definitions . Early definitions are evaluated in the order they are being defined before the superclass constructor of the template is called . #co(){----------------------------------------------------- end-hide0} 言い換えると、事前定義ブロックは、まさに、複数の値定義を含むローカルなブロック であるかのように評価されます。 事前定義は、テンプレートのスーパークラスコンストラクタが呼ばれる前に、 それらが定義された順番で評価されます。 &bold(){Example 5.1.8} : 事前定義は、通常のコンストラクタ・パラメータをもたないトレイトに対して 特に役立ちます。 例: #co(){----------------------------------------------------- bgn-code} trait Greeting { val name: String val msg = "How are you, "+name } class C extends { val name = "Bob" } with Greeting { println(msg) } #co(){----------------------------------------------------- end-code} 上記のコードで、フィールド name は Greeting のコンストラクタが呼び出される前に 初期化されます。 ですから、クラス Greeting 中のフィールド msg は "How are you, Bob" に適切に初期化されます。 #co(){----------------------------------------------------- bgn-hide0} If name had been initialized instead in C's normal class body, it would be initialized after the constructor of Greeting. In that case, msg would be initialized to "How are you, <null>" . #co(){----------------------------------------------------- end-hide0} 代わりに、もし name が C の通常のクラス本体中で初期化されるなら、 それは Greeing のコンストラクタの後に初期化されます。 その場合、msg は "How are you, <null>" と初期化されるでしょう。 #center(){[[前ページ>Spec2.8Chap4b]]  [[目次>Spec2.8和訳]] [[次ページ>Spec2.8Chap5b]]}

表示オプション

横に並べて表示:
変化行の前後のみ表示:
ツールボックス

下から選んでください:

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