2012-07-13 9 views
7

Parece que el uso más común de explicitly-typed self references de Scala se encuentra en el "Cake pattern", en el que las dependencias de un módulo se declaran como:Utilidad de referencias auto escritas explícitamente en el modelo de la torta

class Foo { this: A with B with C => 
    // ... 
} 

En general, ignorando el modelo de la torta por un momento, A, B y C puede referirse a cualquier cosa de nivel de tipo, tal como un parámetro de tipo:

class Outer[A, B, C] { 
    class Inner { this: A with B with C => 
    // ... 
    } 
} 

... o un miembro de tipo abstracto:

class Outer { 
    type A 
    type B 
    type C 
    class Inner { this: A with B with C => 
    // ... 
    } 
} 

En ninguno de estos casos podríamos haber escrito abstract class Inner extends A with B with C, porque A, B y C no son conocidos por ser los rasgos. Las auto referencias explícitamente tipadas son necesarias aquí. Sin embargo, sólo he visto el patrón de la torta hecha con rasgos:

trait A { def a } 
trait B { def b } 
trait C { def c } 
class Foo { this: A with B with C => 
    // ... 
} 

En este caso, en vez podemos escribir directamente abstract class Foo extends A with B with C, que si no me equivoco tiene el mismo significado. ¿Estoy en lo correcto? Si no, ¿cómo difieren? y si es así, ¿por qué parece que todos usan la auto referencia explícitamente tipada?

+0

posible duplicado de [¿Cuál es la diferencia entre Scala auto-tipos y subclases de rasgos?] (Http://stackoverflow.com/questions/1990948/what-is-the-difference-between-scala-self -types-and -it-subclasses) – sschaef

+1

@sschaef diferente pregunta allí, pero uno de los comentarios de Daniel en su respuesta podría ser la respuesta que estoy buscando ... Parece ser similar a la herencia 'pública' vs.' protegida 'herencia en C++? – mergeconflict

+0

Para mí, ambas preguntas parecen querer saber lo mismo: difieren en clases abstractas frente a rasgos que tienen la misma dirección. ¿O entendí fundamentalmente algo mal? – sschaef

Respuesta

6

Parece que hay dos diferencias principales que pasa por alto:

  1. Aunque tanto la explícita de tipo auto anotación y el simple extends palabra clave describen una relación "es-un" relación entre dos tipos, esa relación es no es visible externamente en el primer caso:

    scala> trait T 
    defined trait T 
    
    scala> class C { this: T => } 
    defined class C 
    
    scala> implicitly[C <:< T] 
    <console>:10: error: Cannot prove that C <:< T. 
    

    Esta es una buena cosa, ya que en el modelo de la torta que usted no quiere que su objeto "módulo" sea inadvertidamente, utilizado polimórfica como uno de los rasgos en que se depende

  2. As noted explicitly by Mushtaq y indirectly by Daniel, las dependencias pueden ser cíclicas cuando se utilizan anotaciones de tipo propio. Las dependencias cíclicas son muy comunes, y no necesariamente malas (suponiendo que los componentes interdependientes no se requieren para la inicialización, o que de alguna manera podemos tie the knot entre ellos), por lo que este es otro claro beneficio de las anotaciones de tipo propio sobre la herencia.

1

Cuando usa la herencia, toma decisiones sobre el orden de inicialización. Cuando usa self-types, lo deja abierto.

Existen otras diferencias, pero creo que la mayoría de ellas son detalles de implementación y pueden desaparecer. I saber algunos de ellos son.

+1

Hubiera preferido "cuando usas la herencia, Dios mata a un gatito". – mergeconflict

+0

En una nota más seria ... No entiendo por qué mencionas los tipos dependientes de ruta aquí; ¿hacen una diferencia en la elección entre usar 'extends' contra self types? – mergeconflict

+0

@mergeconflict Pensando en el pasado, las clases que en realidad se están extendiendo suelen ser de nivel superior: las anidadas generalmente se mencionan dentro de ellas. Creo que voy a descartar eso de la respuesta, pero la orden de inicialización es una preocupación. Existen otras diferencias, pero me han corregido antes los poderes superiores en el sentido de que muchos de ellos son detalles de implementación en lugar de diseño. –

Cuestiones relacionadas