2009-10-19 15 views
6

Bene, sto imparando Scala, quindi questa domanda potrebbe essere troppo semplice per la maggior parte delle persone.Scala: come ereditare uno "slot statico"?

In Java che può avere una scanalatura statica (funzione o variabile) in una classe, e poi avrò quello slot in classi ereditate troppo.

In Scala non ho slot statici, ma ho oggetti companion. Ma sto scoprendo che quegli oggetti non fanno parte della classe ereditata, quindi se ho due classi Person e Student, e Persona ha un oggetto compagno con una variabile all:List che restituisce un elenco di tutte le persone così posso fare Person.all, Mi aspettavo di poter fare anche Student.all, ma non è questo il caso.

C'è un modo per ottenere lo stesso comportamento che otterrei in Java?

Grazie!

risposta

13

teoricamente parlando, il comportamento di Java a questo riguardo è molto rotto. Il fatto che le sottoclassi ereditino i membri statici non ha alcun senso da un punto di vista orientato agli oggetti. La statica non è altro che una fantasia, una visione globale. L'ereditarietà è qualcosa che si vede a livello di classe, ma le statistiche non sono realmente a livello di classe (dal momento che sono globali), quindi l'ereditarietà non dovrebbe applicarsi. Il fatto che funzioni in Java è ... inquietante.

Scala ha davvero preso la strada maestra in questo reparto; qualcosa per cui dovremmo essere tutti grati. Come già detto in un'altra risposta, il modo corretto di definire "ereditato" statica è quello di estrarre i membri ereditati fuori in un tratto:

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

class Person { 
    ... 
} 

object Person extends Inherited 

class Student extends Person { 
    ... 
} 

object Student extends Inherited 

Può sembrare inutilmente più prolisso di Java, ma credetemi quando dico che il la semantica è molto meno sorprendente di conseguenza.

4

Gli oggetti in Scala non sono entità di livello di classe come le statiche sono in Java. Sono semplicemente una definizione di classe e un'istanza singleton in uno.

un oggetto associato è un caso speciale che permette la condivisione di dati privati ​​tra esso e la sua classe compagno.

Gli oggetti possono estendere le classi, ma non altri oggetti. Dopotutto un 'oggetto' è solo un'istanza singleton - la definizione di classe di un 'oggetto' è nascosta.

E 'ragionevole aspettarsi che il rapporto speciale tra gli oggetti da compagnia e le classi compagno di proiettare una gerarchia classe aggiuntiva sugli oggetti da compagnia?

Sospetto che il modo migliore per ottenere una dipendenza tra persona e studente sia delegare.

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

Non so se questo è quello che volevi dire, ma un oggetto associato può estendersi da alcuni tratti/classi:

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

Afaics, le risposte di Walter Chang di Daniel Spiewak e sembrano fornire due copie separate della lista all. Non ho provato quanto segue, ma spero che questo fornisca il contorno corretto anche se ha errori.

class Person 
class Student extends Person 

object Person { 
    val all: List[Person] 
} 

quindi entro Student, accesso tramite Person.all

Se si desidera fornire l'accesso tramite Student.all poi

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

Un altro modo per farlo, permetterebbe di dichiarare la statica (cioè Singleton oggetto) in un tratto da ereditare.

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

class Person extends StaticAll 
class Student extends Person 

Quindi accedere con StaticAll#Static.all. Penso che sia corretto e non StaticAll.Static.all. Di nuovo questo è tutto fuori di testa, non ho provato nulla. Per favore correggi i miei errori.

+0

L'errore è che ci sono due copie separate della lista. Il fatto è che non tutto è una lista, ma un riferimento. Prego. –

+0

Ero abbastanza nuovo a Scala quando ho scritto questo commento. Mi rendo conto ora che il tratto di Walter Chang dichiara un riferimento non inizializzato, quindi il suo codice non contiene 2 copie della lista. Nel mio codice, ho dimenticato di inizializzare la lista val [Person] = List(). Con quel cambiamento, il mio codice sarebbe corretto? –

Problemi correlati