2014-01-23 54 views
2

比方说,我有这样的代码和平:重写类型使用“类型”的关键字和路径依赖的类型

trait Holder { 
    type Value 
    def put(v:Value) 
} 

class JsonHolder extends Holder { 
    override type Value = String 
    def put(v: JsonHolder.this.Value): Unit = {} 
} 

class XmlHolder extends Holder { 
    override type Value = String 
    def put(v: XmlHolder.this.Value): Unit = {} 
} 

object Foo { 
    def main(args: Array[String]) { 
    val jsonHolder = new JsonHolder 
    val xmlHodler = new XmlHolder 
    val valueOfJson = new jsonHolder.Value("AAA") 
    val valueOfXml = new xmlHodler.Value("AAA") 
    jsonHolder.put(valueOfXml) 
    } 
} 

我不明白为什么这个编译。不应该由类型错误jsonHolder.put(valueOfXml)?

如果我改变

type Value 

到这样的事情:

case class Value(content:String) 

,取下覆盖线和其他一切保持原样是类型不匹配错误将实际显示。

那么这两者之间有什么区别,因为放置参数的声明不必改变,行为完全不同?

回答

5

那么,这不是一个类型错误,因为JsonHolder.ValueXmlHolder.Value都是String s。考虑其他类型的别名type。所有类型都将替换为其实际类型。所以,你的代码大致是这样的:

val valueOfJson = new String("AAA") // JsonHolder.Value is a String 
val valueOfXml = new String("AAA") // XmlHolder.Value is a String as well 

而且这样的:

class JsonHolder extends Holder { 
    def put(v: String): Unit = {} 
} 

class XmlHolder extends Holder { 
    def put(v: String): Unit = {} 
} 

如果你的类型之一将是,例如,一个Int那么肯定你会得到一个编译错误:

class JsonHolder extends Holder { 
    override type Value = Int 
    def put(v: JsonHolder.this.Value): Unit = {} 
} 

class XmlHolder extends Holder { 
    override type Value = String 
    def put(v: XmlHolder.this.Value): Unit = {} 
} 

object Foo { 
    def main(args: Array[String]) { 
    val jsonHolder = new JsonHolder 
    val xmlHodler = new XmlHolder 
    //compilation error here - Int doesn't have a String constructor 
    val valueOfJson = new jsonHolder.Value("AAA") 
    val valueOfXml = new xmlHodler.Value("AAA") 
    jsonHolder.put(valueOfXml) 
    } 
} 
+0

好吧,'type'在编译过程中的行为就像一个简单的字符串替换,并且所有的事件只是替换,并且那里没有“智能”。 所以有可能这样做: 而不是'case class Value'将其更改为'abstract class Value',然后在其他两个类中重写它,以便可以修改'Value'类的某些行为? – almendar

+0

你能否描述一下你想用这个做什么?我想到的第一件事是参数化 - Holder [T]',和像JsonHolder这样的类扩展了Holder [String]'。但我想你已经考虑过这个,它可能不适合你的情况 – serejja

+0

其实这并非如此,我有任何问题。我只是在玩我能做的和不能做的路径依赖类型。 – almendar