web-dev-qa-db-ja.com

抽象クラスと特性の違い

可能性のある複製:
Scala traits vs abstract classes

抽象クラスと特性の概念的な違いは何ですか?

90
Red Hyena

クラスは 1つのスーパークラスを拡張 しか使用できないため、1つの抽象クラスしか使用できません。いくつかのクラスを構成する場合、Scalaの方法は mixin class composition を使用することです:(オプション)スーパークラス、独自のメンバー定義、および1つ以上を組み合わせます- traits 。特性は、コンストラクタパラメータを持つことができないという点でクラスと比較して制限されています( scalaリファレンスマニュアル と比較してください)。

クラスと比較した特性の制限は、多重継承の典型的な問題を回避するために導入されています。継承階層に関して多少複雑なルールがあります。これが実際に重要な階層を避けることが最善かもしれません。 ;-)私の知る限り、同じシグネチャを持つ2つのメソッド/ 2つの異なる特性から同じ名前を持つ2つの変数を継承する場合にのみ問題になります。

70

特性の1つの側面は、それらがstackableであることです。制限された形式のAOPを許可する(アドバイスについて)。

trait A{
    def a = 1
}

trait X extends A{
    override def a = {
        println("X")
        super.a
    }
}  


trait Y extends A{
    override def a = {
        println("Y")
        super.a
    }
}

scala> val xy = new AnyRef with X with Y
xy: Java.lang.Object with X with Y = $anon$1@6e9b6a
scala> xy.a
Y
X
res0: Int = 1

scala> val yx = new AnyRef with Y with X
yx: Java.lang.Object with Y with X = $anon$1@188c838
scala> yx.a
X
Y
res1: Int = 1

superの解像度は、継承階層の線形化を反映しています。

53
Thomas Jung

概念的には、特性はそれ自体ではなく、クラスのコンポーネントです。そのため、通常、コンストラクターはなく、「独立した」ことを意図していません。

独立した意味を持つ場合は抽象クラスを使用し、オブジェクト指向の方法で機能を追加したい場合は特性を使用することをお勧めします。 この2つが不明な場合の場合、すべてのメソッドが1つのことを中心に展開している場合、おそらく特性が必要になることがあります。

(言語固有ではない)例では、従業員が「Person」と「Cloneable」の両方を拡張する必要がある場合、Personを基本クラス、Cloneableをトレイトにします。

14
Oak

少なくともScalaでは、特性システムにはサブクラスで親の優先度を宣言する明示的な方法があり、多重継承に関連する典型的な問題、つまり同じシグネチャを持つ継承メソッドとの競合を回避します。

特性はJavaインターフェースに似ていますが、メソッドの実装が許可されています。

5
Illotus