Scala 为什么使用类型化变量可以使代码正常工作
这很有效Scala 为什么使用类型化变量可以使代码正常工作,scala,Scala,这很有效 trait SomeTrait { type T def write2( s: String): T } case class C() extends SomeTrait { type T = String override def write2(s:String): T = s } 但事实并非如此 trait SomeTrait { def write2[T]( s: String): T } case class C() ex
trait SomeTrait {
type T
def write2( s: String): T
}
case class C() extends SomeTrait {
type T = String
override def write2(s:String): T = s }
但事实并非如此
trait SomeTrait {
def write2[T]( s: String): T
}
case class C() extends SomeTrait {
override def write2(s: String): String =s }
依我的推理,他们似乎很相似。为什么编译器会给出“方法不重写任何内容”错误?有什么方法可以使这项工作正常进行吗?这将编译:
trait T {
def write2[T]( s: String): T
}
case class C() extends T {
override def write2[T](s: String): T =s.asInstanceOf[T]
}
write2
返回一个T,而不是一个字符串(这就是第二个覆盖不起作用的原因,以及上述代码中丑陋转换的必要性)这编译:
trait T {
def write2[T]( s: String): T
}
case class C() extends T {
override def write2[T](s: String): T =s.asInstanceOf[T]
}
write2
返回一个T,而不是一个字符串
(这就是为什么您的第二个重写不起作用的原因,以及上面代码中对于丑陋的转换的必要性)您在第二个代码段中的特征定义并不意味着它的实现对于某些类型T
,必须有一个方法write2
,但它必须有一个方法write2
,该方法接受类型参数T
这意味着,如果你有一个值v:SomeTrait
,你应该能够
val stringed: String = v.method2[String]("foo")
val inted: Int = v.method2[Int]("foo")
第二个代码段中的trait定义并不意味着对于某些类型T
,它的实现必须有一个方法write2
,但它必须有一个方法write2
,该方法接受一个类型参数T
这意味着,如果你有一个值v:SomeTrait
,你应该能够
val stringed: String = v.method2[String]("foo")
val inted: Int = v.method2[Int]("foo")
如果使用此定义:
trait T {
def write2[T]( s: String): T
}
考虑一些使用这种特性的客户。例如:
def doSomething(t: T): Unit = {
val s: String = t.write2[String]("hello")
val n: Int = t.write2[Int]("world")
val d: Double = t.write2[Double]("!")
println(s + n.toString + d.toString)
}
我不知道s、n和d的值是什么,但从理论上讲,从编译器的角度来看,这是对trait的完美有效使用。因此,为了真正覆盖write2[T]
方法,您必须为所有可能的类型T
提供有效的行为
与之相比:
trait T2 {
type T
def write2( s: String): T
}
甚至:
trait T3[T] {
def write2(s: String): T
}
然后,当呼叫者使用它时:
def doSomething(t: T2): Unit = {
val x = t.write2("hello") // always returns type t.T
}
def doSomething[T](t: T3[T]): Unit = {
val x = t.write2("hello") // always returns type T
}
只有一种可能的类型可以返回,一旦你有了这个特性的一个具体实例。因此,要覆盖该方法,只需覆盖该类型的行为。如果使用此定义:
trait T {
def write2[T]( s: String): T
}
考虑一些使用这种特性的客户。例如:
def doSomething(t: T): Unit = {
val s: String = t.write2[String]("hello")
val n: Int = t.write2[Int]("world")
val d: Double = t.write2[Double]("!")
println(s + n.toString + d.toString)
}
我不知道s、n和d的值是什么,但从理论上讲,从编译器的角度来看,这是对trait的完美有效使用。因此,为了真正覆盖write2[T]
方法,您必须为所有可能的类型T
提供有效的行为
与之相比:
trait T2 {
type T
def write2( s: String): T
}
甚至:
trait T3[T] {
def write2(s: String): T
}
然后,当呼叫者使用它时:
def doSomething(t: T2): Unit = {
val x = t.write2("hello") // always returns type t.T
}
def doSomething[T](t: T3[T]): Unit = {
val x = t.write2("hello") // always returns type T
}
只有一种可能的类型可以返回,一旦你有了这个特性的一个具体实例。因此,要重写该方法,您只需重写该类型的行为。请以不同的方式命名您的类型参数和基本特征,这样会少一点混乱…更新,谢谢请以不同的方式命名您的类型参数和基本特征,这样会少一点混乱…更新,谢谢此编译,但是根本没有用。@AlexeyRomanov的目标不是让它“有用”,而是解释为什么T
不是一个类型String
,OP的重写将不会编译该编译,但根本没有用。@AlexeyRomanov的目标不是让它“有用”但是请解释为什么T
不是类型String
,OP的重写不会编译