Scala函数方差和覆盖 [英] Scala Function Variance and Overriding

查看:462
本文介绍了Scala函数方差和覆盖的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm having a little problem understanding variance of methods when overloading.

虽然返回类型中的协方差可以完美地起作用

While this perfectly works due to covariance in the return type

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                                      
}

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

this one fails even though functions are contravariant in their parameter types.

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
}

我在这里出错了什么?任何指针?

What am I getting wrong here? Any pointers?

问候,
raichoo

Regards, raichoo

推荐答案

这里有两件事:


  1. 一个函数和一个方法 不是一回事

  2. 方法不是多态的参数'的类型

您的测试人员方法是一种方法,不是a Function1 。可以使用下划线语法将其提升为函数:

Your tester method is a method, not a Function1. It can be lifted into a function using the underscore syntax:

val f = (new FooTest[String]).tester _ // Fasel => Bla

此函数在其输入类型中将是反变量。 (值得一提的是,函数无法参数化并且还值得说我必须有一个 Foo 或<$ c $的实例c> FooTest 以获取 tester 方法的函数对象。这当然是从第一次观察开始的!)

This function will be contra-variant in its input type. (It's worth saying, however, that functions cannot be parameterized and also worth saying that I had to have an instance of Foo or FooTest in order to get a function object for the tester method. This of course follows from the first observation!)

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

A function is an object, it cannot be overridden as that makes no sense. Methods can be overridden. However, as I say above, the overriding is not polymorphic in the method's parameter types. So for example:

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

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

上面示例中的两个方法是两个独立的方法:动态调度仅起作用在方法目标(即调用它的对象)上。

The two methods in my example above are two separate methods: dynamic dispatch works only on the method target (i.e. the object on which it is being called).

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

In the above, example, if you remove the override declaration, the code will compile. If you run the following:

(new B).foo(1)   //prints A 1
(new B).foo("s") //prints B s

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

This is because, although both methods are called foo, they are completely different methods (i.e. I have overloaded foo, not overridden it). It's best understood as being that a method's arguments' (incl their types) form part of that method's unique name. One method overrides another only if they have exactly the same name.

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

Essentially you have confused what are two separate and un-related things in your question, which I will put down for clarity:


  • Function1 上的方差注释定义一个函数作为另一个函数的子类型意味着什么(因此可赋值到给定类型的引用)。

  • 可以在子类上重写方法语言规范概述了何时发生此类重写的规则。

  • The variance annotations on Function1 define what it means for one function to be a subtype of another (and hence assignable to a reference of a given type).
  • Methods can be overridden on subclasses and the language specification outlines rules for when such overriding takes place.

这篇关于Scala函数方差和覆盖的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆