2011-11-09 10 views
12

estoy empezando con Scala y esto me pareció un poco raro. En java que podría hacer algo como esto:¿Por qué las clases que no se extienden a otras clases deben extenderse desde rasgos? (with does not work)

interface Foo{} 

public class Bar implements Foo{} 

que estoy tratando de hacer algo similar con Scala, pero no funciona:

trait Foo; 
class Bar with Foo; // This doesn't work! 

Tengo que usar el "extiende" palabra clave :

class Bar extends Foo; // This works OK! 

Ahora, está bien, pero no es lo que quería.

Otra cosa extraña he observado es que dado toda clase de Scala se extiende desde AnyRef (ver esta imagen de scala-lang.org: http://www.scala-lang.org/sites/default/files/images/classhierarchy.png) i puede hacer esto:

class Bar extends AnyRef with Foo; // This works too! 

Por lo tanto, lo que me estoy perdiendo ? ¿No tiene sentido usar un rasgo sin extenderlo?

¡Gracias!

Respuesta

21

primera nota que la extiende/implementa diferencia dice nada al compilador que no lo sabría. No quiero decir que sea malo, solo que el lenguaje podría haber hecho lo contrario. En C#, escriba class A : B, C, D en lugar de class A extends B implements C, D y class A implements B, C, D. Así que puedes pensar que el extends de Scala es como el colon y with como la coma.

Sin embargo, en los viejos tiempos, solía ser class Bar with Foo. Cambió cuando Scala se retiró 2.0 en 2006. Vea the change history.

Creo recordar (no estoy seguro) que la razón fue simplemente que class Bar with Foo no lee bien.

En Scala, A with B es la intersección de los tipos A y B. Un objeto es del tipo A with B si es ambos del tipo A y del tipo B. Por lo tanto, class A extends B with C se puede leer class A extiende el tipo B with C. No existe tal cosa con class A with B.

+0

¡Buena explicación, gracias! – santiagobasulto

3

Programming in Scala (2nd ed) discute rasgos en el Capítulo 12. Se observa con respecto a extends:

Usted puede utilizar la palabra clave extends para mezclar en un rasgo; en ese caso, hereda implícitamente la superclase del rasgo. Por ejemplo, en el listado 12.2, clase Frog subclases AnyRef (la superclase de Philosophical) y mezclas en Philosophical.

(Aquí, Philosophical es un rasgo.)

lo tanto, su razonamiento es exactamente correcto.

Sobre el tema AnyRef, debe leer sobre Scala class hierarchy y top types. (AnyRef no es el tipo superior, pero está bastante cerca.)

+0

¡Tengo ese libro! ¿Por qué lo extraño? Gracias @Emil – santiagobasulto

8

Si vienes de Java, puede sonar extraño al principio (era lo mismo para mí), pero en realidad ahora me parece que es una sintaxis más regular que Java, donde necesito decir explícitamente si quiero implement o extend otra clase/interfaz. Pero creo que es más una cuestión de gusto personal.

En realidad, no importa si está diciendo extends o implements. Ambos representan el mismo tipo de relación entre dos cosas: es un (a diferencia de la delegación y la composición, que representan tiene una relación). Aquí, por ejemplo, se pueden encontrar algunos más información al respecto:

http://www.javacamp.org/moreclasses/oop/oop5.html

sólo tratar de sustituir extends, implements, with con is a y se hace más clara.

En Scala también tiene otras variaciones de la relación is a. Por ejemplo tipos de auto:

trait Bar { 
    self: Foo => 
    // ... 
} 

Con esto usted está diciendo, que no se extiende Bar/implementos Foo directamente, sino a todas las otras clases, que desean ampliar Bar también debe extenderse Foo.

Los tipos propios pueden permitir cosas interesantes. Por ejemplo, dos clases/rasgos que dependen unos de otros:

class Bar extends Foo { 
    def sayHello(name: String) = println("Hello, " + name) 

    greet() 
} 

trait Foo { 
    this: Bar => 

    def greet() = sayHello("User") 
} 

new Bar() // prints: Hello, User 
+0

vea también http://www.levinotik.com/2012/09/14/scala-abstract-classes-traits-and-self-types/ – ZiglioUK

+0

esta es una respuesta interesante, especialmente los "self types" parte. ¡Gracias! – asgs

Cuestiones relacionadas