наследование скалы и проблема нижней границы - PullRequest
2 голосов
/ 06 ноября 2011

У меня есть некоторые проблемы с наследованием и нижними границами в scala;Я попытаюсь объяснить это на примере: у меня есть класс Person с такой подписью:

def doSomething[P<%Person](persons :List[P]) {
}

Я также создал дочерний класс Worker, и его метод doSomething выглядит следующим образом:

override def doSomething(persons: List[Worker]) {
}

Однако при этом возникает ошибка, в которой говорится, что Worker.doSomething () ничего не переопределяет?

Ответы [ 2 ]

4 голосов
/ 06 ноября 2011

Определенный метод не может переопределить универсальный метод (хотя конкретный класс может расширять универсальный класс), потому что универсальный метод говорит, что он будет работать, пока вы передаете ему любой подкласс человека.Конкретный метод не будет принимать любой подкласс;это займет всего Worker.

3 голосов
/ 06 ноября 2011

Вы не можете наследовать таким образом.Это нарушает принцип замещения Лискова .Я покажу, почему это так.Предположим, что вы можете скомпилировать эти классы:

class Person {
    def doSomething[P<%Person](persons :List[P]) {
    }
}

class Worker extends Person {
    override def doSomething(persons: List[Worker]) {
    }
}

Теперь эта простая программа не будет работать:

val p1: Person = new Worker
val p2: Person = new Person
p1.doSomething(List(p2))

Поскольку p2 не является Worker, этот вызов недопустим.Однако, поскольку p1 является Person, этот вызов действителен!Это противоречие является результатом предложенного вами переопределения.

Но это еще хуже!Это ТАКЖЕ не сработает:

p1.doSomething[Worker](List(p1))

Теперь, несмотря на то, что он пропускает список работников, как и ожидалось p1, он не работает, потому что doSomething в Worker не работаетНе ожидайте параметр типа .Однако метод doSomething из Person объявил, что параметр типа должен быть передан!Опять же, противоречие является результатом предложенного вами переопределения.

Помните, что наследование - это тип отношений is-a .Если Worker - это Person, то он должен действовать как Person во всех отношениях, ожидая, что Person будет действовать.Если вы не хотите создавать такие отношения, не используйте наследование.

...