2009-10-19 8 views
6

私はScalaを学んでいますので、この質問はほとんどの人にとっては基本的すぎるかもしれません。スカラ:「静的スロット」を継承する方法は?

Javaでは、静的なスロット(関数または変数)をクラスに含めることができます。次に、そのスロットを継承したクラスにも配置します。

私は静的スロットはありませんが、コンパニオンオブジェクトがあります。しかし、私はそれらのオブジェクトが継承されたクラスの一部ではないことを知っています。したがって、私が2つのクラスPersonStudentを持っていて、Personが変数all:Listを持つコンパニオンオブジェクトを持っていますので、すべての人のリストを返すのでPerson.all、私はStudent.allでもできると思っていたが、そうではない。

javaと同じ動作をする方法はありますか?

ありがとうございます!

答えて

13

は理論的に言えば、この点でのJavaの動作は非常にです壊れた。サブクラスが静的メンバーを継承するという事実は、実際にはオブジェクト指向の観点からは意味をなさない。統計は、実際上、スコープの広いグローバルなものに過ぎません。継承はクラスレベルで見られるものですが、実際はクラスレベルではありません(グローバルなので、継承は適用されません)。それがJavaで実行されているという事実は邪魔です。

Scalaは本当にこの部門で大きな道を歩んでいます。我々は皆に感謝しなければならない何か。別の答えで述べたように、静の「継承」を定義するための正しい方法は、形質に出て継承されたメンバーを抽出することである。

trait Inherited { 
    def foo() { ... } 
    def bar(i: Int) = ... 
} 

class Person { 
    ... 
} 

object Person extends Inherited 

class Student extends Person { 
    ... 
} 

object Student extends Inherited 

これは、Javaよりも不より冗長に見えるかもしれませんが、私はと言うとき私を信頼しますセマンティクスは結果として驚くほど驚くことではありません。

4

Scalaのオブジェクトは、静的なものはJavaのクラスレベルのエンティティではありません。それらは単にクラス定義であり、シングルトンのインスタンス化はクラス定義に組み込まれます。

コンパニオンオブジェクトは、コンパニオンオブジェクトとそのコンパニオンクラス間でプライベートデータを共有できる特殊なケースです。

オブジェクトはクラスを拡張できますが、他のオブジェクトは拡張できません。結局のところ、 'オブジェクト'は単なるシングルトンインスタンスであり、 'オブジェクト'のクラス定義は隠されています。

コンパニオンオブジェクトとコンパニオンクラスの特別な関係が、コンパニオンオブジェクトに追加のクラス階層を投影することを期待するのは妥当ですか?

PersonとStudentの間の依存関係を実現する最良の方法は、委任することだと思います。

object Person { val all = List(1,2,3) } 
object Student { val all = Person.all.filter(_ % 2 == 0) } 
6

これはあなたが何を意味するのかである場合、私は知りませんが、コンパニオンオブジェクトは、いくつかの特徴/クラスから拡張することができます:

class Person 
class Student extends Person 

trait Aggregation[T] { 
    val all: List[T] 
} 

object Person extends Aggregation[Person] { 
    val all: List[Person] = List(new Person, new Person) 
} 

object Student extends Aggregation[Student] { 
    val all: List[Student] = List(new Student, new Student) 
} 

println(Person.all) // prints all persons 
println(Student.all) // prints all students 
-1

Daniel SpiewakとWalter Changの答えは、allリストの2つの別個のコピーを提供するように見えます。私は以下のことをテストしなかったが、エラーがあっても正しいアウトラインを提供することを願っています。その後、Student

class Person 
class Student extends Person 

object Person { 
    val all: List[Person] 
} 

あなたは静的に宣言できるようになり、その後、

object Student { 
    def all() = Person.all 
} 

Student.all経由でそれを行うための別の方法をアクセスを提供したい場合はPerson.all経由のアクセス(すなわちシングルトンオブジェクト)を継承することができます。

trait StaticAll { 
    object Static { val all: List[Person] } 
} 

class Person extends StaticAll 
class Student extends Person 

StaticAll#Static.allでアクセスしてください。私はそれが正しいと思うし、StaticAll.Static.allではないと思う。これも私の頭の上から外れています。私はこれをテストしませんでした。私の誤りを訂正してください。

+0

エラーは、リストの2つの別個のコピーがあることです。事実、すべてがリストではなく、参考文献です。どういたしまして。 –

+0

私はこのコメントを書いたとき、私はScalaをかなり新しくしました。私はウォルター・チャンの特性が初期化されていない参照を宣言したことを認識しています。したがって、彼のコードはリストの2つのコピーではありません。私のコードでは、私はvalを初期化することを忘れてList [Person] = List()。その変更により、私のコードは正しいでしょうか? –

関連する問題