Здесь происходит две вещи:
- Функция и метод не одно и то же
- Методы не являются полиморфными по типам своих параметров
Ваш 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
, а не переопределено it). Лучше всего понимать, что аргументы метода (включая их типы) образуют часть уникального имени этого метода . Один метод переопределяет другой, только если они имеют точно такое же имя .
<Ч />
По сути, вы перепутали две отдельные и не связанные вещи в вашем вопросе, которые я поясню для ясности:
- Примечания к дисперсии
Function1
определяют, что означает, что одна функция является подтипом другой (и, следовательно, присваивается для ссылки на данный тип).
- Методы могут быть переопределены на подклассах, а в спецификации языка изложены правила, когда такое переопределение имеет место.