A val
не принимает аргументов, потому что он вычисляется и сохраняется в поле. Но я мог бы просто отослать вас к обширным постам, которые я делал последние два дня в списках рассылки.
Или, скорее, давайте рассмотрим это с точки зрения Java, поскольку Scala совместима с Java на уровне jvm и, безусловно, должна подчиняться правилам jvm. Начнем с первого класса:
abstract class X {
def expensiveOperation(p: Int => Boolean) : List[Int]
}
Теперь давайте расширим его:
abstract class Y extends X {
override val expensiveOperation: ((Int) => Boolean) => List[Int]
}
Итак, из Java мы знаем, что класс X
имеет метод expensiveOperation
, который получает Function1[Int, Boolean]
и возвращает List[Int]
.
Теперь мы идем в класс Y
. Естественно, он должен определять тот же метод, но он также должен определять метод получения expensiveOperation
, который не получает аргументов и возвращает Function1[Function1[Int, Boolean],List[Int]]
.
Это может быть работоспособным, если этот дополнительный метод не существует и в X
. Итак, давайте определим это:
class Z extends Y {
override val extensiveOperation = new Function1[Function1[Int, Boolean], List[Int]] {
def apply(p: Int => Boolean) = List range (1, 10) filter p
}
}
Как это определяется? Копирует ли Scala тело apply
как тело для expensiveOperation
(получающего параметр, а не получающего)? Это все еще может быть работоспособным. Давайте попробуем что-то еще, хотя:
class W(f: ((Int) => Boolean) => List[Int]) extends Y {
override val extensiveOperation = f
}
Теперь, как мы можем переопределить получение параметра extensiveOperation
? Я полагаю, мы могли бы написать это так:
override def extensiveOperation(p: Int => Boolean) = extensiveOperation.apply(p)
Это выполнимо. Но я лично считаю это немного запутанным. Мое предложение: напишите короткий SID и получите соглашение по списку рассылки Scala. Однако без кода для его реализации я не думаю, что у него есть много шансов быть принятым - Scala должна отслеживать каждую типизированную val
, чтобы определить, переопределяет ли она def
или нет.