Scala函数方差和覆盖

rai*_*hoo 5 inheritance overriding scala variance

我在解决重载时方法的方差方面遇到了一些问题.

虽然由于返回类型的协方差,这完美地起作用

class Bla 
class Fasel extends Bla 

trait Test[A] {
 def tester(): Bla = new Bla
}

class FooTest[A](a: A) extends Test[A] {
 override def tester(): Fasel = new Fasel                                      
}
Run Code Online (Sandbox Code Playgroud)

即使函数在参数类型中是逆变的,这个也会失败.

class Bla 
class Fasel extends Bla 

trait Test[A] {
 def tester(a: Fasel): Bla = new Bla                                           
}

class FooTest[A](a: A) extends Test[A] {
 override def tester(a: Bla): Fasel = new Fasel
}
Run Code Online (Sandbox Code Playgroud)

我在这里弄错了什么?有什么指针吗?

问候,raichoo

oxb*_*kes 11

这里有两件事:

  1. 功能和方法不是一回事
  2. 方法的参数类型不是多态的

你的tester方法是一种方法,而不是一种Function1方法.可以使用下划线语法将其提升为函数:

val f = (new FooTest[String]).tester _ // Fasel => Bla
Run Code Online (Sandbox Code Playgroud)

此功能在其输入类型中将具有矛盾的变体.(值得一提的是,函数不能参数化,也值得说我必须有一个实例Foo或者FooTest为了获得该tester方法的函数对象.这当然是从第一次观察开始的!)

函数是一个对象,它不能被覆盖,因为没有意义.方法可以被覆盖.但是,正如我上面所说,覆盖在方法的参数类型中不是多态的.例如:

class A {
  def foo(a : Any) = println("A: " + a)
}

class B extends A {
  override def foo(s : String) = println("B " + s) //will not compile!
}
Run Code Online (Sandbox Code Playgroud)

上面我的例子中的两个方法是两个独立的方法:动态调度仅适用于方法目标(即调用它的对象).

在上面的示例中,如果删除override声明,代码将被编译.如果您运行以下内容:

(new B).foo(1)   //prints A 1
(new B).foo("s") //prints B s
Run Code Online (Sandbox Code Playgroud)

这是因为,尽管两种方法都被调用foo,但它们是完全不同的方法(即我已经过载 foo,没有重写它).最好的理解是方法的参数'(包括它们的类型)构成该方法唯一名称的一部分.一种方法只有在具有完全相同的名称时才会覆盖另一种方法.


基本上你已经混淆了你的问题中的两个独立和不相关的东西,为了清楚起见我将放下:

  • 方差注释Function1定义了一个函数作为另一个函数的子类型意味着什么(因此赋予给定类型的引用).
  • 可以在子类上重写方法,并且语言规范概述了何时发生此类重写的规则.

  • 得到它:3.3.1 MethodTypes谢谢:) (2认同)