自己型と特性サブクラスの違いは何ですか? 質問する

自己型と特性サブクラスの違いは何ですか? 質問する

特性の自己タイプA:

trait B
trait A { this: B => }

A拡張も行わない具体的なクラスに混在させることはできないBと述べています。

一方、次のとおりです。

trait B
trait A extends B

「(具象または抽象)クラスが混在すると、AB も混在する」と述べています。

これら 2 つのステートメントは同じことを意味しているのではないですか? self-type は、単純なコンパイル時エラーの可能性を生み出すだけであるようです。

何が足りないのでしょうか?

ベストアンサー1

主に以下の用途に使用されます依存性注入ケーキパターンのような、素晴らしい記事Scalaにおける依存性注入のさまざまな形式をカバーしており、その中にはCakeパターンも含まれています。Googleで「CakeパターンとScala」と検索すると、プレゼンテーションやビデオを含む多くのリンクが見つかります。今のところ、別の質問

さて、自己型とトレイトの拡張の違いは何かというと、それは簡単です。 とするとB extends A、は にB なりますA。自己型を使用する場合、には がB 必要ですA。自己型によって作成される特定の要件が 2 つあります。

  1. が拡張される場合はB、をミックスインする必要がAあります。
  2. 具体的なクラスが最終的にこれらの特性を拡張/ミックスインする場合、何らかのクラス/特性が を実装する必要がありますA

次の例を考えてみましょう。

scala> trait User { def name: String }
defined trait User

scala> trait Tweeter {
     |   user: User =>
     |   def tweet(msg: String) = println(s"$name: $msg")
     | }
defined trait Tweeter

scala> trait Wrong extends Tweeter {
     |   def noCanDo = name
     | }
<console>:9: error: illegal inheritance;
 self-type Wrong does not conform to Tweeter's selftype Tweeter with User
       trait Wrong extends Tweeter {
                           ^
<console>:10: error: not found: value name
         def noCanDo = name
                       ^

Tweeterが のサブクラスである場合User、エラーは発生しません。上記のコードでは、 が使用されるたびにが必要でしたが、には が提供されなかったため、エラーが発生しました。上記のコードがまだスコープ内にある状態で、次のことを考慮してください。UserTweeterUserWrong

scala> trait DummyUser extends User {
     |   override def name: String = "foo"
     | }
defined trait DummyUser

scala> trait Right extends Tweeter with User {
     |   val canDo = name
     | }
defined trait Right 

scala> trait RightAgain extends Tweeter with DummyUser {
     |   val canDo = name
     | }
defined trait RightAgain

を使用するとRight、 をミックスインするという要件は満たされます。ただし、上記の 2 番目の要件は満たされません。を拡張するクラス/特性Userの実装の負担は依然として残ります。UserRight

両方のRightAgain要件が満たされます。 およびUserの実装Userが提供されます。

より実用的な使用例については、この回答の冒頭にあるリンクを参照してください。しかし、これで理解していただけたと思います。

おすすめ記事