Переопределенный метод имеет общую подпись, которая несовместима с общей подписью базового метода.

Я только что обновился до 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
}
Другие вопросы по тегам