Spec2.8Chap4a

第 4 章 基本的な宣言と定義

構文:

   Dcl         ::=   'val' ValDcl
                 |   'var' VarDcl
                 |   'def' FunDcl
                 |   'type' {nl} TypeDcl
    PatVarDef  ::=   'val' PatDef 
                 |   'var' VarDef
    Def        ::=   PatVarDef
                 |   'def' FunDef
                 |   'type' {nl} TypeDef
                 |   TmplDef

A declaration introduces names and assigns them types. It can form part of a class definition (§5.1) or of a refinement in a compound type (§3.2.7).

A definition introduces names that denote terms or types. It can form part of an object or class definition or it can be local to a block. Both declarations and definitions produce bindings that associate type names with type definitions or bounds, and that associate term names with types .

宣言 は名前を導入し、それらに型を割り当てます。 それはクラス定義 (§5.1) の一部あるいは、 複合型 (§3.2.7) における細別 (refinement) の一部を形成します。

定義 は項(term)あるいは型を表す名前を導入します。 それはオブジェクトあるいはクラス定義の一部を形成したり、 ブロックにローカルにできます。 宣言と定義の両方とも、 型名に型定義あるいは境界を結びつける 束縛 を生み出し、それは項名に型を結びつけます。

The scope of a name introduced by a declaration or definition is the whole statement sequence containing the binding. However, there is a restriction on forward references in blocks: In a statement sequence s1 ... sn making up a block, if a simple name in si refers to an entity defined by sj , where j >= i , then none of the definitions between and including si and sj may be a value or variable definition .

宣言/定義によって導入された名前のスコープは、束縛を含む文並び全体です。 しかし、ブロック中での前方参照には制限があります。: ブロックを構成する文並び s1 ... sn 中で、もし si 中の単純名が sj によって定義されたエンティティを参照するなら (ただしここで j >= i)、 そのときは si と sj の間およびそれらを含めたいかなる定義も、 値あるいは変数定義であってはなりません。



4.1 値宣言と定義 (Value Declarations and Definitions)

構文:

   Dcl         ::=   'val' ValDcl
   ValDcl      ::=   ids ':' Type
   Def         ::=   'val' PatDef
   PatDef      ::=   Pattern2 {',' Pattern2} [':' Type] '=' Expr
   ids         ::=   id {',' id}

A value declaration val x : T introduces x as a name of a value of type T . A value definition val x : T = e defines x as a name of the value that results from the evaluation of e. If the value definition is not recursive, the type T may be omitted , in which case the packed type (§6.1) of expression e is assumed. If a type T is given, then e is expected to conform to it .

値宣言 val x : T は、型 T の値の名前として x を導入します。

値定義 val x : T = e は、e の評価から得られる値の名前として x を定義します。 もし値定義が再帰的でないなら、型 T は省略されることがあり、その場合は、 式 e のパックされた型(§6.1)が想定されます。 もし型 T が与えられていれば、e はそれに適合することが要請されます。

Evaluation of the value definition implies evaluation of its right-hand side e, unless it has the modifier lazy. The effect of the value definition is to bind x to the value of e converted to type T . A lazy value definition evaluates its right hand side e the first time the value is accessed .

A constant value definition is of the form

値定義の評価は、修飾子 lazy がなければ、その右辺 e の評価を意味します。 値定義の効果は、型 T に変換された e の値に x を束縛することです。 遅延評価値(lazy value definition)定義は、値が最初にアクセスされたときに、 その右辺 e を評価します。

定数値定義(constant value definition) は、次の形です。

   final val x = e

where e is a constant expression (§6.24) . The final modifier must be present and no type annotation may be given. References to the constant value x are themselves treated as constant expressions; in the generated code they are replaced by the definition 's right-hand side e .

ここで e は定数式(§6.24)です。 final 修飾子は必須ですが、型アノテーションは全くないかもしれません。 定数値 x への参照は、それ自身定数式として扱われます。 つまり、それらは生成コード中で定義の右辺 e によって置き換えられます。

Value definitions can alternatively have a pattern (§8.1) as left-hand side. If p is some pattern other than a simple name or a name followed by a colon and a type, then the value definition val p = e is expanded as follows:

値定義は、左辺にパターン (§8.1)をとることができます。 もし p が、単純名あるいは名前の後にコロンと型が続くパターン以外なら、 値定義 val p = e は次のように展開されます:

1.もしパターン p が束縛変数 x1,...,xn (n > 1) を持っているなら

   val $x = e match {case p => {x1,...,xn}}
   val x1 = $x._1
     ...
   val xn = $x._n

ここで $x は新規の名前です。

2.もし p がただ 1 つの束縛変数 x を持つなら:

   val x = e match { case p => x }

3.もし p が束縛変数を持たないなら:

   e match { case p => ()}


Example 4.1.1 : 次は値定義の例です

   val   pi = 3.1415
   val   pi: Double = 3.1415        // 最初の定義と等価
   val   Some(x) = f()              // パターン定義
   val   x :: xs = mylist           // 中置パターン定義

最後の 2 つの定義は、次のように展開されます。

   val x = f() match { case Some(x) => x }
   val x$ = mylist match { case x :: xs => {x, xs} }
   val x = x$._1
   val xs = x$._2

The name of any declared or defined value may not end in _= .

宣言されたあるいは定義された値のいかなる名前も _= で終わってはなりません。

値宣言 val x1,...,xn : T は、値宣言の並び val x1 : T ; ...; val xn : T の略記表現です。値定義 val p1,...,pn = e は、値定義の並び val p1 = e ; ...; val pn = e の略記表現です。値定義 val p1,...,pn : T = e は、値定義の並び val p1 : T = e ; ...; val pn : T = e の略記表現です。



4.2 変数宣言と定義 (Variable Declarations and Definitions)

構文:

   Dcl         ::= 'var' VarDcl
   Def         ::= 'var' VarDef
   VarDcl      ::= ids ':' Type
   VarDef      ::= PatDef
                 | ids ':' Type '=' '_'

変数宣言 var x : T は、次のように定義された ゲッター関数 x と セッター関数 x_= 宣言に等価です:

   def x : T
   def x_= (y : T): Unit

変数宣言を含むクラスの実装では、 変数定義を使ってそれら変数を定義することがあり、 あるいはまた、直接的にゲッター、セッター関数を定義することがあります。

変数定義 var x : T = e は、型 T をもつミュータブル変数と、 式 e で与えられた初期値を導入します。型 T は省略されることがあり、 その場合は、e の型が想定されます。 もし T が与えられていれば、 e はそれに適合することが要請されます (§6.1)。

変数定義は、左辺にパターン (§8.1)をとることができます。 変数定義 var p = e (ただしここで p は単純名あるいは 名前の後にコロンと型が続く以外のパターン) は、 p 中の自由な名前が値ではなく ミュータブル変数として導入されること以外、 値定義 val p = e と同じ方法 (§4.1) で展開されます。

The name of any declared or defined variable may not end in _= .

いかなる宣言されたあるいは定義された名前も、_= で終わってはなりません。

変数定義 var x : T = _ は、テンプレートのメンバーとしてだけ 現われることができます。 これは型 T のミュータブルなフィールドとデフォルトの初期値を導入します。 デフォルト値は、次のように型 T に依存します:

   0       T が Int あるいはその部分領域型の 1 つのとき
   0L      T が Long のとき
   0.0f    T が Float のとき
   0.0d    T が Double のとき
   false   T が Boolean のとき
   {}      T が Unit のとき
   null    他のすべての型 T について

When they occur as members of a template, both forms of variable definition also introduce a getter function x which returns the value currently assigned to the variable , as well as a setter function x _= which changes the value currently assigned to the variable. The functions have the same signatures as for a variable declaration. The template then has these getter and setter functions as members, whereas the original variable cannot be accessed directly as a template member.

それらがテンプレートのメンバーとして現れるときは、 変数定義の両形式とも、変数に現在割り当てられている値を返すゲッター関数 x が 導入され、変数に現在割り当てられている値を変えるセッター関数 x_= も導入されます。関数は、変数宣言については同じシグニチャを持ちます。 このときテンプレートはそれらゲッターとセッター関数をメンバーとして持ちますが、 一方、オリジナルの変数には、 テンプレートメンバーとして直接アクセスすることはできません。


Example 4.2.1 : 次の例は、Scala において プロパティ が どのようにシミュレートされるかを示します。 これは、hours、minutes、seconds で表される更新可能な整数フィールドを持つ、 時間値からなるクラス TimeOfDayVar を定義しています。 この実装は、 それらフィールドに正しい値のみ代入できるようにするテストを含んでいます。 一方、ユーザーコードは、 それらのフィールドに普通の変数とまったく同じようにアクセスします。

   class TimeOfDayVar {
     private var h: Int = 0
     private var m: Int = 0
     private var s: Int = 0
   
     def hours              =  h
     def hours_= (h: Int)   =  if (0 <= h && h < 24) this.h = h
                               else throw new DateError()
   
     def minutes            =  m
     def minutes_= (m: Int) =  if (0 <= m && m < 60) this.m = m
                               else throw new DateError()
   
     def seconds            =  s
     def seconds_= (s: Int) =  if (0 <= s && s < 60) this.s = s
                               else throw new DateError()
   }
   val d = new TimeOfDayVar
   d.hours = 8; d.minutes = 30; d.seconds = 0
   d.hours = 25                  // DateError 例外送出

変数宣言 var x1,...,xn : T は、変数宣言の並び var x1 : T ; ...; var xn : T の略記表現です。 変数定義 var x1,...,xn = e は、 変数定義の並び var x1 = e ; ...; var xn = e の略記表現です。 変数定義 var x1,...,xn : T = e は、変数定義の並び var x1 : T = e ; ...; var xn : T = e の略記表現です。



4.3 型宣言と型エイリアス (Type Declarations and Type Aliases)

構文:

   Dcl         ::= 'type' {nl} TypeDcl
   TypeDcl     ::= id [TypeParamClause] ['>:' Type] ['<:' Type]
   Def         ::= type {nl} TypeDef
   TypeDef     ::= id [TypeParamClause] '=' Type

A type declaration type t[tps] >: L <: U declares t to be an abstract type with lower bound type L and upper bound type U . If the type parameter clause [tps] is omitted, t abstracts over a first-order type, otherwise t stands for a type constructor that accepts type arguments as described by the type parameter clause .

型宣言 type t[tps] >: L <: U は、 t が下限境界型 L と上限境界型 U をもつ抽象型であることを宣言します。 型パラメータ節 [tps] が省略された場合、t は一階型の抽象化であるか、 そうでなければ t は型コンストラクタを表し、 型パラメータ節によって記述されたとして型引数を受け入れます。

If a type declaration appears as a member declaration of a type, implementations of the type may implement t with any type T for which L <: T <: U . It is a compiletime error if L does not conform to U . Either or both bounds may be omitted. If the lower bound L is absent, the bottom type scala.Nothing is assumed. If the upper bound U is absent, the top type scala.Any is assumed.

もし型宣言が型のメンバー宣言として現われるなら、その型の実装は、 t を L <: T <: U である任意の型 T をもつとして実装するかもしれません。 もし L が U に適合しないなら、コンパイルエラーとなります。 いずれかあるいは両方の境界とも省略されるかもしれません。 もし下限境界 L がないなら、最下位の型 scala.Nothing が想定されます。 もし上限境界 U がないなら、最上位の型 scala.Any が想定されます。

A type constructor declaration imposes additional restrictions on the concrete types for which t may stand. Besides the bounds L and U , the type parameter clause may impose higher-order bounds and variances, as governed by the conformance of type constructors (§3.5.2) .

型コンストラクタ宣言は、t が表すであろう具象型に制限を付け加えます。 L と U の境界ほかに、型パラメータ節は、型コンストラクタ (§3.5.2) の適合性によって左右される高階の境界や変位指定を課すかもしれません。

The scope of a type parameter extends over the bounds >: L <: U and the type parameter clause tps itself. A higher-order type parameter clause (of an abstract type constructor tc) has the same kind of scope, restricted to the declaration of the type parameter tc .

型パラメータのスコープは、境界 >: L <: U と型パラメータ節 tps 自身に及びます。 (抽象型コンストラクタ tc の)高階の型パラメータ節は同種のスコープを持ち、 型パラメータ tc の宣言へ制限されます。

To illustrate nested scoping, these declarations are all equivalent: type t[m[x] <: Bound[x], Bound[x]], type t[m[x] <: Bound[x], Bound[y]] and type t[m[x] <: Bound[x], Bound[_]], as the scope of, e.g., the type parameter of m is limited to the declaration of m. In all of them, t is an abstract type member that abstracts over two type constructors: m stands for a type constructor that takes one type parameter and that must be a subtype of Bound , t's second type constructor parameter. t[MutableList, Iterable] is a valid use of t .

ネストしたスコープを説明すると、次は全て同じスコープです。: type t[m[x] <: Bound[x], Bound[x]]、type t[m[x] <: Bound[x], Bound[y]] と type t[m[x] <: Bound[x], Bound[_]]。 例えば、m の型パラメータのスコープは m の宣言に制限されるからです。 これらのすべてにおいて t は、2 つの型コンストラクタ上の抽象である 抽象型メンバーです。:

m は、1 つの型パラメータをとり、 Bound のサブ型でなければならないような型コンストラクタを表します。 ここで Bound は t の 2 番目の型コンストラクタパラメータとなっています。 t[MutableList、Iterable]は、t の有効な使い方です。

A type alias type t = T defines t to be an alias name for the type T . The left hand side of a type alias may have a type parameter clause, e.g. type t[tps] = T . The scope of a type parameter extends over the right hand side T and the type parameter clause tps itself .

型エイリアス type t = T は、t が型 T の別名であることを定義します。 型エイリアスの左辺は型パラメータ節を持っていてもかまいません。 たとえば type t[tps] = T です。型パラメータのスコープは、 右辺 T と型パラメータ節 tps 自身に及びます。

The scope rules for definitions (§4) and type parameters (§4.6) make it possible that a type name appears in its own bound or in its right-hand side. However, it is a static error if a type alias refers recursively to the defined type constructor itself. That is, the type T in a type alias type t[tps] = T may not refer directly or indirectly to the name t . It is also an error if an abstract type is directly or indirectly its own upper or lower bound .

定義(§4)と型パラメータのスコープ規則 (§4.6)では、 型名がそれ自身の境界あるいはその右辺中に現れることを可能としています。 しかし、もし型エイリアスが、定義された型コンストラクタ自身を再帰的に参照するなら、 それは静的エラーです。 すなわち、型エイリアス type t[tps] = T 中の型 T は、 直接的にも間接的にも名前 t を参照できません。 もし抽象型が、直接あるいは間接的にそれ自身の上限/下限境界なら、 それも同じくエラーです。


Example 4.3.1 : 次は正しい型宣言と定義です:

   type   IntList = List[Integer]
   type   T <: Comparable[T]
   type   Two[A] = Tuple2[A, A]
   type   MyCollection[+X] <: Iterable[X]

次は不正です:

   type Abs = Comparable[Abs]     // 再帰的な型エイリアス
   
   type S <: T                    // S, T はそれら自身によって
   type T <: S                    //      境界付けられている
   
   type T >: Comparable[T.That]   // T から選択できない
                                  // T は型であり、値ではない
   type MyCollection <: Iterable  // 型コンストラクタメンバーは明示的に
                                  //      ??? を記述しなければならない。

If a type alias type t[tps] = S refers to a class type S, the name t can also be used as a constructor for objects of type S .

もし型エイリアス type t[tps] = S がクラス型 S を参照するなら、 名前 t は、型 S のオブジェクトのコンストラクタとしても使えます。


Example 4.3.2 : 事前定義済みオブジェクト(Predef object)は、 パラメータ化されたクラス Tuple2 のエイリアスとして、Pair を定める定義を 含んでいます。

   type Pair[+A, +B] = Tuple2[A, B]
   object Pair {
     def apply[A, B](x: A, y: B) = Tuple2(x, y)
     def unapply[A, B](x: Tuple2[A, B]): Option[Tuple2[A, B]] = Some(x)
   }

その結果、任意の 2 つの型 S と T に対して、型 Pair[S, T]は、型 Tuple2[S, T] に等価です。 次のように、Pair は Tuple2 の代わりにコンストラクタとしても使えます。

   val x: Pair[Int, String] = new Pair(1, "abc")



4.4 型パラメータ (Type Parameters)

構文:

   TypeParamClause  ::= '[' VariantTypeParam {',' VariantTypeParam} ']'
   VariantTypeParam ::= {Annotation} ['+' | '-'] TypeParam
   TypeParam ::= (id | '_') [TypeParamClause] ['>:' Type] ['<:' Type] [':' Type]

型パラメータは、型定義、クラス定義と関数定義の中に現れます。 この節では、下限境界 >:L と上限境界 <: U をもつ型パラメータ定義だけについて考え、 コンテキスト境界 : U と 可視境界 <% U については、 あとで §7.4 で議論します。

一階の型パラメータの最も一般的な形は、@a1 ... @an ± t >: L <: U です。 ここで、L と U は、そのパラメータの可能な型引数を制約する下限と上限境界です。 もし L が U に適合しなければ、それは実行時エラーとなります。 ±は 変位指定(variance) 、すなわち、+ も - もオプションの前置子です。 1 つ以上のアノテーションが型パラメータに先行しても構いません。

The names of all type parameters must be pairwise different in their enclosing type parameter clause. The scope of a type parameter includes in each case the whole type parameter clause. Therefore it is possible that a type parameter appears as part of its own bounds or the bounds of other type parameters in the same clause . However, a type parameter may not be bounded directly or indirectly by itself .

すべての型パラメータの名前は、型パラメータ節を囲む中で対で(pairwise) 異なっていなければなりません。 型パラメータのスコープは、それぞれ、 型パラメータ節全体を含みます。 ですから型パラメータは、それ自身の境界の一部あるいは、 同じ節中の他の型パラメータの境界の一部に現れることができます。 しかし型パラメータは、それ自身によっては直接あるいは間接に境界づけられません。

A type constructor parameter adds a nested type parameter clause to the type parameter. The most general form of a type constructor parameter is @a1 ... @an ± t[tps] >: L <: U .

型コンストラクタパラメータは、 ネストした型パラメータ節をその型パラメータに加えます。 型コンストラクタパラメータの最も一般的な形は、 @a1 ... @an ± t[tps] >: L <: U です。

The above scoping restrictions are generalized to the case of nested type parameter clauses, which declare higher-order type parameters. Higher-order type parameters (the type parameters of a type parameter t ) are only visible in their immediately surrounding parameter clause (possibly including clauses at a deeper nesting level) and in the bounds of t . Therefore, their names must only be pairwise different from the names of other visible parameters. Since the names of higher-order type parameters are thus often irrelevant, they may be denoted with a '_', which is nowhere visible .

上記のスコープ制約は、 高階の型パラメータを宣言するネストした型パラメータ節の場合へ一般化されます。 高階の型パラメータ(型パラメータ t の型パラメータ)は、 それらを直に囲むパラメータ節(より深いネストレベルにおける節も含む)中と t の境界中においてだけ、可視です。 そのため、それらの名前は、 他の可視のパラメータ名と対で異なっていなければなりません。 高階の型パラメータの名前は、しばしば重要でないことがあり、 その場合、'_' で表すことができ、名前はどこにも見えません。


Example 4.4.1 : 次は、型パラメータ節の正しい形の例です:

   [S, T]
   [@specialized T, U]
   [Ex <: Throwable]
   [A <: Comparable[B], B <: A]
   [A, B >: A, C >: A <: B]
   [M[X], N[X]]
   [M[_], N[_]]                // 上の節に等価
   [M[X <: Bound[X]], Bound[_]]
   [M[+X] <: Iterable[X]]

次の型パラメータ節は不正です:

    [A >: A]                   // 不正、'A'はそれ自身を境界として持つ
    [A <: B, B <: C, C <: A]   // 不正、'A'はそれ自身を境界として持つ
    [A, B, C >: A <: B]        // 不正、'C'の不正な下限境界 'A'は、
                               // 上限境界 'B' に適合しない。



4.5 変位指定アノテーション (Variance Annotations)

Variance annotations indicate how instances of parameterized types vary with respect to subtyping (§3.5.2). A '+' variance indicates a covariant dependency, a '-' variance indicates a contravariant dependency, and a missing variance indication indicates an invariant dependency .

変位指定アノテーションは、パラメータ化された型のインスタンスがサブ型 (§3.5.2) に関してどのように異なるかを示します。 '+' 変位指定は共変の従属性を表し、'-' 変位指定は反変の従属性を表し、 変位指定がなければ不変の従属性を表します。

A variance annotation constrains the way the annotated type variable may appear in the type or class which binds the type parameter. In a type definition type T[tps] = S, or a type declaration type T[tps] >: L <: U type parameters labeled '+' must only appear in covariant position whereas type parameters labeled '-' must only appear in contravariant position. Analogously, for a class definition class C[tps](ps) extends T { x : S => ...}, type parameters labeled '+' must only appear in covariant position in the self type S and the template T , whereas type parameters labeled '-' must only appear in contravariant position .

変位指定アノテーションは、型パラメータを束縛する型あるいはクラス中において、 アノテーションされた型変数の現れ方に制約を課します。 型定義 type T[tps] = S あるいは型宣言 type T[tps] >: L <: U において、 '+' と印された型パラメータは共変のポジションにのみ現れることができ、他方、 '-' と印された型パラメータは反変のポジションにのみ現れることができます。 同様に、クラス定義 class C[tps](ps) extends T { x : S => ...} においては、 '+' と印された型パラメータは、自己型 S とテンプレート T 中の共変のポジションにのみ現れることができ、 他方、'-' と印された型パラメータは反変のポジションにのみ現れることができます。

The variance position of a type parameter in a type or template is defined as follows . Let the opposite of covariance be contravariance, and the opposite of invariance be itself. The top-level of the type or template is always in covariant position. The variance position changes at the following constructs .

型あるいはテンプレートにおける型パラメータの変位指定のポジションは、 次のように定義されます。 共変の反対は反変、非変の反対はそれ自身とします。 型あるいはテンプレートのトップレベルは、常に共変のポジションです。 変位指定のポジションは、次の言語要素において変化します。

  • The variance position of a method parameter is the opposite of the variance position of the enclosing parameter clause .
  • The variance position of a type parameter is the opposite of the variance position of the enclosing type parameter clause .
  • The variance position of the lower bound of a type declaration or type parameter is the opposite of the variance position of the type declaration or parameter .
  • The type of a mutable variable is always in invariant position .
  • The prefix S of a type selection S#T is always in invariant position .
  • For a type argument T of a type S[... T ...]: If the corresponding type parameter is invariant, then T is in invariant position. If the corresponding type parameter is contravariant, the variance position of T is the opposite of the variance position of the enclosing type S[... T ...] .
  • メソッドパラメータの変位指定のポジションは、取り囲むパラメータ節の変位指定のポジションの反対です。
  • 型パラメータの変位指定のポジションは、取り囲む型パラメータ節の変位指定のポジションの反対です。
  • 型宣言あるいは型パラメータの下限境界の変位指定のポジションは、型宣言あるいは型パラメータの変位指定のポジションの反対です。
  • ミュータブルな変数の型は、常に非変のポジション中にあります。
  • 型選択 S#T の前置子 S は、常に非変のポジション中にあります。
  • 型 S[... T ...] の型引数 T について、もし対応する型パラメータが非変なら、T は非変のポジション中にあります。 もし対応する型パラメータが反変なら、T の変位指定のポジションは S[...T...] を囲む変位指定のポジションの反対です。

References to the type parameters in object-private values, variables, or methods (§5.2) of the class are not checked for their variance position. In these members the type parameter may appear anywhere without restricting its legal variance annotations .

オブジェクト非公開 な値、変数、あるいはクラスのメソッド (§5.2)中の型パラメータへの参照は、 それらの変位指定のポジションはチェックされません。 これらのメンバーでは、型パラメータは、 正しい変位指定アノテーションと限定されずに、どこにでも現われることができます。


Example 4.5.1 : 次の変位指定アノテーションは正しい。

   abstract class P[+A, +B] {
     def fst: A; def snd: B   }

With this variance annotation, type instances of P subtype covariantly with respect to their arguments. For instance,

この変位指定アノテーションでは、P の型インスタンスは、それら引数を共変に サブ型付けします。例えば、

   P[IOException, String] <: P[Throwable, AnyRef]

もし P のメンバーがミュータブルな変数なら、同じ変位指定アノテーションは不正 になります。

   abstract class Q[+A, +B](x: A, y: B) {
     var fst: A = x           // **** error: illegal variance:
     var snd: B = y           // 'A', 'B' が不変のポジションに現れている
   }

もしミュータブルな変数がオブジェクト非公開 なら、クラス定義は再び正しくなります:

   abstract class R[+A, +B](x: A, y: B) {
     private[this] var fst: A = x        // OK
     private[this] var snd: B = y        // OK
   }


Example 4.5.2 : 次の変位指定アノテーションは不正です。 なぜなら、append パラメータ中の反変のポジションに A が現れるからです。

   abstract class Sequence[+A] {
     def append(x: Sequence[A]): Sequence[A]
                    // **** error: illegal variance:
                    // 'A' が反変のポジションに現れている
   }

問題を、下限境界を使って append の型を一般化することで回避できます。

   abstract class Sequence[+A] {
     def append[B >: A](x: Sequence[B]): Sequence[B]
   }


Example 4.5.3 : 次は反変の型パラメータが役に立つ場合です。

   abstract class OutputChannel[-A] {
     def write(x: A): Unit
   }

With that annotation, we have that OutputChannel[AnyRef] conforms to OutputChannel[String]. That is, a channel on which one can write any object can substitute for a channel on which one can write only strings .

このアノテーションにより、OutputChannel[AnyRef] は OutputChannel[String] に適合します。 つまり、任意のオブジェクトを書き込めるチャネルは、 文字列だけを書き込めるチャネルを代理できます。

タグ:

+ タグ編集
  • タグ:

このサイトはreCAPTCHAによって保護されており、Googleの プライバシーポリシー利用規約 が適用されます。

最終更新:2011年02月23日 18:31
ツールボックス

下から選んでください:

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