Переопределенный метод имеет общую подпись, которая несовместима с общей подписью базового метода.
Я только что обновился до Xcode 11.4. Я получаю следующую ошибку:
Overridden method 'equals' has generic signature <T where T : Gradient> which is incompatible with base method's generic signature <T where T : Fill>; expected generic signature to be <T where T : Fill>
https://stackru.com/imag es/72e7db8b329b56f4998e774c2373ff52d337efc8.png
class Fill: Equatable {
func equals<T>(other: T) -> Bool where T: Fill { }
}
func ==<T> (lhs: T, rhs: T) -> Bool where T: Fill {
return lhs.equals(other: rhs)
}
class Gradient: Fill {
override func equals<T>(other: T) -> Bool where T: Gradient { }
}
Как это изменилось?
3 ответа
Пожалуйста, посмотрите эту ветку https://forums.swift.org/t/method-override-with-a-generic-signature-with-requirements-not-imposed-by-the-base-method/33593
Эта ошибка компиляции предотвращает сбой в будущем.
В моем случае я просто исправляю эту ошибку следующим образом:-
override func equals<T>(other: T) -> Bool where T: Fill {
guard let other = other as? Gradient else {
return false
}
...
}
Но есть некоторые похожие ошибки Macaw, поэтому просто замените Gradient на свою проблему с ошибкой, и она исправится.
Причина, по которой вы не можете изменять такие ограничения, заключается в том, что это нарушит принцип замены Лискова. Компилятор никогда не проверял общую сигнатуру переопределенных функций, и это приводило к различным сбоям во время выполнения, поэтому я реализовал эту ошибку в компиляторе Swift 5.2.
Давайте посмотрим на ваш собственный пример, чтобы понять, что не так. Можно написать следующий код:
let fill1: Fill = Fill()
let fill2: Fill = Gradient()
let isEqual = fill2.equals(other: fill1)
Это неверно, потому что Gradient.equals(other:)
требует other
унаследовать от Gradient
. Однако, посколькуfill2
имеет статический тип Fill
, Я могу обойти это ограничение и передать значение типа Fill
вместо.
Если Gradient.equals(other:)
пытается получить доступ к свойству или функции на other
который существует только в экземпляреGradient
, ваш код просто упадет во время выполнения, потому что это свойство или функция не будут доступны на Fill
:
class Fill: Equatable {
func equals<T>(other: T) -> Bool where T: Fill { ... }
}
class Gradient: Fill {
private(set) var id: String = UUID().uuidString
override func equals<T>(other: T) -> Bool where T: Gradient {
return id == other.id // crash if `other` is value of type `Fill`
}
}
Итак, компилятор теперь запрещает вам добавлять несовместимые ограничения при переопределении функции.
Теперь есть два основных способа решить проблему: изменить код и избежать добавления несовместимых ограничений в переопределенной функции или выполнить проверку времени выполнения в переопределенной функции с помощью as?
или type(of:)
чтобы проверить, действительно ли переданное значение удовлетворяет новым ограничениям, а затем попробуйте его использовать:
override func equals<T>(other: T) -> Bool where T: Gradient {
if type(of: other) == Fill.self { return false }
return id == other.id // okay
}