循環依存関係から始めましょう。
trait A {
selfA: B =>
def fa: Int }
trait B {
selfB: A =>
def fb: String }
ただし、このソリューションのモジュール性は、次のように自己型をオーバーライドできるため、最初に表示されるほど大きくはありません。
trait A1 extends A {
selfA1: B =>
override def fb = "B's String" }
trait B1 extends B {
selfB1: A =>
override def fa = "A's String" }
val myObj = new A1 with B1
ただし、self 型のメンバーをオーバーライドすると、元のメンバーにはアクセスできなくなりますが、継承を使用して super を介して引き続きアクセスできます。したがって、継承を使用することで実際に得られるのは次のとおりです。
trait AB {
def fa: String
def fb: String }
trait A1 extends AB
{ override def fa = "A's String" }
trait B1 extends AB
{ override def fb = "B's String" }
val myObj = new A1 with B1
Cake パターンの微妙な点をすべて理解しているとは言えませんが、モジュール性を強制する主な方法は、継承や自己型ではなく合成によるものだと思います。
継承バージョンの方が短いですが、self 型よりも継承を好む主な理由は、self 型で初期化順序を正しくするのがはるかに難しいからです。ただし、継承ではできなくても、self 型でできることがいくつかあります。Self 型は型を使用できますが、継承には次のようにトレイトまたはクラスが必要です。
trait Outer
{ type T1 }
trait S1
{ selfS1: Outer#T1 => } //Not possible with inheritance.
次のこともできます。
trait TypeBuster
{ this: Int with String => }
インスタンス化することはできませんが。型から継承できない絶対的な理由はわかりませんが、型コンストラクターの特性/クラスがあるため、パスコンストラクタークラスと特性があると便利だと確信しています。残念ながら
trait InnerA extends Outer#Inner //Doesn't compile
これがあります:
trait Outer
{ trait Inner }
trait OuterA extends Outer
{ trait InnerA extends Inner }
trait OuterB extends Outer
{ trait InnerB extends Inner }
trait OuterFinal extends OuterA with OuterB
{ val myV = new InnerA with InnerB }
またはこれ:
trait Outer
{ trait Inner }
trait InnerA
{this: Outer#Inner =>}
trait InnerB
{this: Outer#Inner =>}
trait OuterFinal extends Outer
{ val myVal = new InnerA with InnerB with Inner }
もっと共感されるべき点の 1 つは、トレイトがクラスを拡張できることです。これを指摘してくれた David Maclver に感謝します。これが私自身のコードの例です:
class ScnBase extends Frame
abstract class ScnVista[GT <: GeomBase[_ <: TypesD]](geomRI: GT) extends ScnBase with DescripHolder[GT] )
{ val geomR = geomRI }
trait EditScn[GT <: GeomBase[_ <: ScenTypes]] extends ScnVista[GT]
trait ScnVistaCyl[GT <: GeomBase[_ <: ScenTypes]] extends ScnVista[GT]
ScnBase
Swing Frame クラスから継承するため、自己型として使用し、最後に (インスタンス化時に) 混合することができます。ただし、val geomR
トレイトを継承して使用する前に初期化する必要があります。したがって、 の事前初期化を強制するクラスが必要ですgeomR
。クラスScnVista
は、それ自体が継承できる複数の直交特性によって継承できます。複数の型パラメーター (ジェネリック) を使用すると、代替形式のモジュール性が提供されます。