Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/email/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 为什么使用类型化变量可以使代码正常工作_Scala - Fatal编程技术网

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的重写不会编译