Невозможно вызвать дополнительную функцию в протоколе при наследовании от обобщенного класса c - PullRequest
0 голосов
/ 24 апреля 2020

Если подкласс реализует необязательную функцию, вызов функции по протоколу работает как положено. А именно, он будет вызывать дочерний метод, даже если он не реализован в родительском классе.

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

Вот игровая площадка, показывающая проблему. ..

import UIKit

@objc
protocol MyProtocol {
  @objc optional func foo()
}

// MARK: - Works

class Parent: MyProtocol { }
class Child: Parent {
  func foo() { print("Child.foo()") }
}

(Child() as MyProtocol).foo?()
// ✅ Outputs `Child.foo()`



// MARK: - Broken

class BrokenParent<T>: MyProtocol { }
class BrokenChild: BrokenParent<String> {
  func foo() { print("BrokenChild.foo()") }
}

(BrokenChild() as MyProtocol).foo?()
// ❌ Bug: does not output anything

Почему это происходит и какие обходные пути существуют, чтобы это исправить?

Xcode 11.4.1

Ответы [ 2 ]

0 голосов
/ 25 апреля 2020

Просто добавьте '@ obj c' в свое удовольствие c:

@objc func foo() { print("BrokenChild.foo()") }
0 голосов
/ 24 апреля 2020

Не уверен, почему это происходит, но я подозреваю, что @objc protocol вызывает использование среды выполнения Objective- C для отправки события, а Swift имеет некоторый закулисный код, чтобы сделать простой случай работоспособным (и опущен более сложное наследование + родовой случай c). Хотя я могу быть совершенно неправ в этом и хотел бы узнать реальную причину.

Вот два фрагмента, которые можно добавить на ту же площадку, на которых показаны доступные обходные пути, а именно: (1) реализация метода в родительский класс или (2) с помощью ключевого слова @objc в имени метода.

// MARK: - Fixed 1

class FixedParent1<T>: MyProtocol {
  open func foo() {}
}
class FixedChild1: FixedParent1<String> {
  override func foo() { print("FixedChild1.foo()") }
}

(FixedChild1() as MyProtocol).foo?()
// ✅ Outputs `FixedChild1.foo()`



// MARK: - Fixed 2

class FixedParent2<T>: MyProtocol {}
class FixedChild2: FixedParent2<String> {
  @objc func foo() { print("FixedChild2.foo()") }
}

(FixedChild2() as MyProtocol).foo?()
// ✅ Outputs `FixedChild2.foo()`
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...