8

<:特性の抽象型をwithとnotwithでオーバーライドしたい=(ここでの回答のようにScala Upper Bounds:valueはtypeパラメーターのメンバーではありません)。

ケーキ柄を使いたいのですが、うまくいきません。理由がわかりません。

trait A {
  def ping = println("ping")
}

trait Cake {
  type T
}

trait S { this: Cake =>
  type T = A
  def t: T
  t.ping
}

OK、この例は実行されますが、私の実際のユースケースでは、タイプをオーバーライドしたいのですが、では<:ありません=。t関数にアクセスできないようです。なぜですか?

trait S { this: Cake =>
  type T <: A
  def t: T
  t.ping
}

エラーを返すvalue ping is not a member of S.this.T

4

1 に答える 1

15

これはScalaの型システムの欠点です。ミックスインのメンバーを決定するとき、Scalaは2つのルールを使用します。1つは、concreteが常にabstractをオーバーライドすることです。次に、2つのメンバーが両方とも具象であるか、両方が抽象である場合、線形化の順序で後で来る方が優先されます。

さらに、特性の自己タイプ

trait S { this: C => ... }

暗黙的に拡張されます

trait S { this: S with C => ... }

特性Sの定義にS内でアクセスできるようにします。あなたの場合、特性Sは次のように表示されます。

trait S { this: S with Cake =>
  type T = A
  def t: T
  t.ping
}

さて、Tが具象である限り、Cakeの抽象的なTをオーバーライドするので、これは問題ありません。しかし、Tが抽象である場合、CakeのTは線形化の順序の後半に来て、勝ちます。そして、そのTには上限がないため、メンバーはpingを実行しません。これを修正する1つの方法は、次のように記述して線形化の順序を変更することです。

trait S { this: Cake with S =>
  type T <: A
  def t: T
  t.ping
}

線形化の順序に従って単一のメンバーを選択するのではなく、抽象型メンバーのすべての制約がミックスインにマージされるという別のルールがScalaにあると、よりクリーンになります。これは将来検討したい変更ですが、下位互換性に注意する必要があります。

于 2012-04-19T07:21:03.230 に答える