我在理解重载时方法的变化方面遇到了一些问题。
尽管由于返回类型的协方差,这非常有效
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
}
即使函数在它们之间是互变的,此函数也会失败
参数类型。
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
}
我这是怎么了?有指针吗?
问候,
雷乔
最佳答案
这里有两件事:
您的
tester
方法是一种方法,而不是Function1
。可以使用下划线语法将其提升为一个函数:val f = (new FooTest[String]).tester _ // Fasel => Bla
此函数的输入类型将是反变的。 (不过,值得一提的是,函数无法参数化,也必须说我必须拥有
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!
}
在我上面的示例中,这两个方法是两个单独的方法:动态分配仅在方法目标(即在其上被调用的对象)上起作用。
在上面的示例中,如果删除了
override
声明,则代码将被编译。如果运行以下命令:(new B).foo(1) //prints A 1
(new B).foo("s") //prints B s
这是因为,尽管这两种方法都称为
foo
,但它们是完全不同的方法(即,我已重载了foo
,但未覆盖它)。最好的理解是方法的参数(包括它们的类型)构成该方法唯一名称的一部分。仅当一种方法具有完全相同的名称时,它才会覆盖另一种方法。从本质上讲,您已经混淆了您的问题中的和无关的两件事是什么,为了清楚起见,我将其简化为:
Function1
上的方差注释定义了一个函数成为另一个函数的子类型(并因此可分配给给定类型的引用)的含义。 关于inheritance - Scala函数的方差和覆盖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4297019/