特性継承と自己型アノテーションの違い
-
19-09-2019 - |
質問
Scala では、コンストラクトを見てきました。
trait T extends S
そして
trait T { this: S =>
同様のことを達成するために使用されます(つまり、 S
インスタンスを作成する前に定義する必要があります)。それらの違いは何ですか?なぜ一方を他方よりも使用するのでしょうか?
解決
私は、依存関係の管理のために自己のタイプを使用すると思います。
ただ、例として:
trait FooService
trait FooRemoting { this : FooService => }
trait FooPersistence { this : FooService => }
object Services extends FooService with FooRemoting with FooPersistence
さて、FooRemotingとFooPersistence場合の両方がFooServiceから継承されているだろう、とFooServiceがメンバーとメソッドを持って、どのようにサービスは次のようになりますか?
継承のためのに対し、我々のようなものを持っていると思います
trait Iterator[T] {
def hasNext : boolean
def next : T
}
trait InfiniteIterator[T] extends Iterator[T] {
def hasNext = true
}
他のヒント
自己型注釈を使用すると、循環依存関係を表現することができます。たとえばます:
trait A extends B
trait B { self: A => }
これは、単純な継承では不可能である。
質問をしてから、次のような投稿を見つけました。
スピロス・ザベラス パブリック インターフェイスとして特性を使用し、実装クラスによって混合する必要があるヘルパーとして自己型を使用することについて説明します。
結論から言うと、 トレイト内のメソッド実装 そうすると、インターフェースを汚染するリスクがあります 抽象的な方法によるそれらの特性の これは、 具体的なメソッドであり、無関係です の主な責任で 習性。この問題の解決策は次のとおりです これらの抽象メソッドを その他の特性と特性の構成 self 型の注釈を一緒に使用する そして多重継承。
例えば:
trait PublicInterface { this: HelperTrait =>
// Uses helperMethod
}
trait HelperTrait {
def helperMethod = // ...
}
class ImplementationClass extends PublicInterface with HelperTrait
スカラ座のツアー 抽象型メンバーでの self 型アノテーションの使用について説明しています。おそらく、それは不可能です。 extend
抽象型メンバー(?)
答えは、「真円度」です。だけでなくます。
自己型注釈は私のために相続の基本的な問題を解決:あなたはあなたが何であるかを使用することはできませんから継承するもの。 セルフタイプでは、すべてが簡単になります。
私のパターンは以下の通りであると縮退ケーキとして考えることができます:
trait A { self: X => def a = reuseme}
trait B { self: X => def b = a }
class X extends A with B { def reuseme=null }
きれいに型指定された滞在しながらあなたは、どこにでもアセンブリ内から呼び出すことができ、複数の行動のクラスを爆発することができます。 あまりにも頻繁に痛みを伴う間接の必要はありません(と誤って)ケーキのパターンで識別。
過去10年間の複雑なJavaのDIフレームワークのハーフ(そうでない場合は全体)を入力することなく、当然のことながら、これを行うために捧げてきました。 まだこのドメインでJAVAを使っている人は明らかに自分の時間を失うされています。「SCALAのouakbar」
私はこの質問は古いです知っているが、私はいくつかの明確化と例を追加したいと思います。
トレイトの継承とセルフタイプの間の三つの主要な違いがあります。
意味
AがBを拡張する場合は、継承オブジェクトパラダイムの最もカップリングとの関係の一つであり、それは、AがBであることを意味する。
タグ、我々は次のコードを持っているとしましょう
trait Animal {
def stop():Unit = println("stop moving")
}
class Dog extends Animal {
def bark:String = "Woof!"
}
val goodboy:Dog = new Dog
goodboy.bark
// Woof!
私たちは、犬の の動物であることを言っています。犬がいるので、私たちは、それは両方の方法を理解し、bark
するメッセージstop
とgoodboy
を送ることができます。
さて、
私たちは新しい形質を持っていると仮定trait Security {
this: Animal =>
def lookout:Unit = { stop(); println("looking out!") }
}
この時間セキュリティは動物ではなく、私たちはセキュリティが動物であることを断言した場合、彼らは一緒に使用することができます異なる概念、ある意味的に正しくないことになるので、それは大丈夫です。
だから今、私たちは、犬の新しい種類を作成することができ、
val guardDog = new Dog with Security
guardDog.lookout
// stop moving
// looking out!
guardDog
は犬、動物とセキュリティです。セキュリティが強化された犬であるので、それはstop
、bark
とlookout
を理解します。
しかし、我々はこのような新しい犬を作成した場合はどうなりますか?
val guardDog2:Dog = new Dog with Security
guardDog2.lookout // no such method!
guardDog2
はちょうど犬であるので、我々はlookout
メソッドを呼び出すことはできません。 (okok、それはセキュリティが強化された犬だが、我々はちょうど犬を参照してください)。
循環依存
セルフタイプは、私たちは型間の循環依存を作成することができます。
trait Patient {
this: Reader =>
def isQuite:Boolean = isReading
def isSlow:Boolean = true
}
trait Reader {
this: Patient =>
def read():Unit = if(isSlow) println("Reading Slow...") else println("Reading Fast...")
def isReading = true
}
val person = new Patient with Reader
次のコードはコンパイルされません。
trait Patient extends Reader { /** code **/}
trait Reader extends Patient { /** code **/ }
コードのこの種の依存性注入(ケーキパターン)で非常に一般的である。
汎用性
使用特性が同じであるが、形質線形化のおかげで、最終的な結果は異なる場合がありますので、それらが使用される順序を決めることができ、私たちの特性を使用しています誰が、少なくとも最後になりましたが。
通常の継承では、我々はそれを行うことはできません。、特性とクラス間の関係は固定されてます。
trait Human {
def isGoodForSports:Boolean
}
trait Programmer extends Human {
def readStackOverflow():Unit = println("Reading...")
override def isGoodForSports: Boolean = false
}
trait Sportsman extends Human {
def play():Unit = println("Playing something")
override def isGoodForSports: Boolean = true
}
val foo = new Programmer with Sportsman
foo.isGoodForSports
// true
val bar = new Sportsman with Programmer
bar.isGoodForSports
// false
は、これが役立ちます願っています。
、私は自己型注釈を理解しようとしていたし、基本的には答えで失われた、と何とかのためのセルフ型注釈の使用に焦点を当て、あなたの質問、のバリエーションを巡回終わってしまいました依存関係を記述します。
だからここに私は、すなわち自己型注釈が十分に示しているユースケース、サブタイプとしてのthisの型安全なケースのようなものの説明を投稿します:
http://programming-scala.labs.oreilly.com/ch13。 htmlの#SelfTypeAnnotationsAndAbstractTypeMembersする
これは偶然この質問に終わる(と、私のように、:-)を探索を開始する前に、Scalaの本を読む時間を持っていなかった)人に参考になることを期待します。