2012-01-01 20 views
8

me gustaría hacer algo como esto (ejemplo se simplifica, pero contiene todas las piezas cruciales):Puzzle - exposición de una sub-miembro público de miembro privado con el tipo de encargo

class Master 
{ 
    type DataType = Int 
    var counter : DataType = 0 
} 

class Slave(private val master : Master) 
{ 
    val counter = master.counter // (*) 
} 

Y aquí (*) me sale error:

private value master escapes its defining scope as part of type Slave.this.master.DataType

val counter = master.counter

entiendo el error, pero no entiendo la razón - el tipo es parte de la clase Master, no el objeto master, lo que es importante si la clase es privada, no es un objeto Bueno, al menos en teoría.

Es fácil hacer una solución rápida:

val counter : Master#DataType = master.counter 

pero creo que esta es una versión explícita del mismo código exactamente como antes, que "sólo" lleva más de mecanografía. ¿Es esta una característica entonces?

PREGUNTA:

Puede un tipo (aquí DataType) ser dependiente del objeto, y no a la clase (es decir, definición de tipo por ejemplo de la clase) en Scala?

Respuesta

14

usted está equivocado cuando se piensa

this is an explicit version of the exactly same code as before

Master#DataType y master.DataType son dos diferentes tipos.

master.DataType es el tipo de las instancias DataType que tienen master como objeto externo. En otras palabras, precisamente lo que pregunta, pero obviamente entonces masteres parte del tipo, y el tipo no puede exponerse si master no lo está.

Master#DataType es el tipo de cualquier instancia DataType para cualquier objeto externo (equivalente a Master.DataType en Java).

respuesta al comentario:

miembros de tipo pueden redefinirse en una subclase (incluyendo una subclase anónima que contiene sólo un objeto), pero sólo por un tipo compatible. Y en su ejemplo, DataType ya es concreto en Master, por lo que la única clase compatible con él es en sí misma. Así que algo como

val a = new Master { 
    override type DataType = String 
} 

no typecheck, lo cual tiene sentido: se obtendría var counter: String = 0, lo cual es absurdo. Pero

val a = new Master { 
    override type DataType = Int 
} 

funcionará (pero no es demasiado útil).

Por lo tanto, solo tiene sentido anular abstract tipo de miembros. Pero están revisados ​​por tipos de la misma manera que las clases internas, por lo que a.DataType generalmente no se considera lo mismo que b.DataType, ¡incluso si no pueden ser diferentes en realidad!

+0

Gracias, por lo que si entiendo esto correctamente (sin embargo, no lo leí en "Programación en Scala", creo, o tal vez se deslizó), puede definir el tipo por instancia de la clase, no solo por clase . – greenoldman

+0

Gracias por la actualización, esto es muy valioso, desafortunadamente no puedo dejar de votar su publicación más de 1 :-) – greenoldman

+0

Esta es una de esas cosas útiles en Scala que puede ser un "error" cuando proviene de otros lenguajes OOP. Respuesta muy sucinta; vale la pena mi upvote;). – TechNeilogy

Cuestiones relacionadas