2009-10-19 11 views
6

Bueno, estoy aprendiendo Scala, así que esta pregunta puede ser demasiado básica para la mayoría de las personas.Scala: ¿cómo heredar una "ranura estática"?

En Java, puedo tener una ranura estática (función o variable) en una clase, y también tendré esa ranura en las clases heredadas.

En Scala no tengo ranuras estáticas, pero tengo objetos complementarios. Pero estoy descubriendo que esos objetos no son parte de la clase heredada, así que si tengo dos clases Person y Student, y Person tiene un objeto complementario con una variable all:List que devuelve una lista de todas las personas para que pueda hacer Person.all, También esperaba poder hacer Student.all, pero ese no es el caso.

¿Hay alguna forma de obtener el mismo comportamiento que obtendría en Java?

Gracias!

Respuesta

13

Teóricamente hablando, el comportamiento de Java en este sentido es muy roto. El hecho de que las subclases hereden miembros estáticos realmente no tiene sentido desde un punto de vista orientado a objetos. La estática no es más que un globo terráqueo de lujo. La herencia es algo que se ve en el nivel de clase, pero la estática realmente no está en el nivel de clase (ya que son globales) por lo que la herencia no debería aplicarse. El hecho de que lo haga en Java es ... perturbador.

Scala realmente ha tomado el camino más alto en este departamento; algo por lo que todos deberíamos estar agradecidos. Como se ha mencionado en otra respuesta, la forma correcta para definir "heredó" la estática es extraer los miembros heredados a cabo en un rasgo:

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

class Person { 
    ... 
} 

object Person extends Inherited 

class Student extends Person { 
    ... 
} 

object Student extends Inherited 

Puede parecer innecesariamente más prolija que Java, pero confía en mí cuando digo que la la semántica es mucho menos sorprendente como resultado.

4

Los objetos en Scala no son entidades a nivel de clase, como las estáticas en Java. Son simplemente una definición de clase e instanciación de singleton, todo en uno.

Un objeto complementario es un caso especial que permite el intercambio de datos privados entre él y su clase complementaria.

Los objetos pueden ampliar las clases, pero no otros objetos. Después de todo, un 'objeto' es solo una instancia única: la definición de clase de un 'objeto' está oculta.

¿Es razonable esperar que la relación especial entre los objetos complementarios y las clases complementarias proyecte una jerarquía de clases adicional en los objetos complementarios?

Sospecho que la mejor manera de lograr una dependencia entre Persona y Estudiante es delegar.

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

No sé si esto es lo que quería decir, sino un objeto acompañante puede extenderse desde algunos rasgos y/o clases:

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

Las respuestas de Afaics, Daniel Spiewak y Walter Chang parecen proporcionar dos copias separadas de la lista all. No probé lo siguiente, pero espero que esto proporcione el esquema correcto incluso si tiene errores.

class Person 
class Student extends Person 

object Person { 
    val all: List[Person] 
} 

entonces dentro Student, acceso a través de Person.all

Si desea proporcionar acceso a través de Student.all continuación

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

Otra manera de hacerlo, le permitiría declarar la estática (es decir, Singleton objeto) en un rasgo que se heredará.

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

class Person extends StaticAll 
class Student extends Person 

Luego de acceso con StaticAll#Static.all. Creo que es correcto y no StaticAll.Static.all. Una vez más, todo esto está fuera de mi cabeza, no probé nada de esto. Por favor corrige mis errores

+0

El error es que hay dos copias separadas de la lista. El hecho es que no todo es una lista, sino una referencia. De nada. –

+0

Era bastante nuevo en Scala cuando escribí este comentario. Ahora me doy cuenta de que el rasgo de Walter Chang declara una referencia no inicializada, por lo que su código no contiene 2 copias de la lista. En mi código, olvido inicializar val List [Person] = List(). Con ese cambio, ¿mi código sería correcto? –

Cuestiones relacionadas