Как создать протокол с расширяющимся типом универсальной функции

#swift #generics #protocols #swift-protocols

#swift #дженерики #протоколы #swift-протоколы

Вопрос:

Я пытаюсь создать протокол с универсальной функцией, где T не просто равно типу, но и расширяет его.

 class MainItem {}
class Item1: MainItem {}
class Item2: MainItem {}

protocol MyProtocol {
    func myFunc<T: MainItem>() -> T // T extends MainItem
}

class ClassA: MyProtocol {
    func myFunc() -> Item1 { // not MainItem
        return Item1()
    }
}

class ClassB: MyProtocol {
    func myFunc() -> Item2 { // not MainItem
        return Item2()
    }
}
  

Но я получаю эту ошибку

Тип ‘ClassA’ не соответствует протоколу ‘MyProtocol’

потому Item1 что не равно MainItem (оно расширяет его). Как вы можете заставить его работать?

Например, в Java все можно сделать с помощью абстрактного класса:

 abstract class MyProtocol {
    abstract <T extends MainItem> T myFunc()
}
  

Комментарии:

1. @Dimple пожалуйста, не добавляйте нерелевантные теги. Тег iOS следует использовать только для вопросов, конкретно касающихся платформы iOS, но этот вопрос явно не зависит от платформы и касается только функции языка программирования Swift.

Ответ №1:

Дженерики не подходят для ваших требований. Когда вы объявляете универсальную функцию в протоколе, параметр универсального типа будет означать, что одна и та же функция работает для всех типов, которые удовлетворяют ограничению универсального типа, но сигнатура функции все равно должна быть неизменной для всех соответствующих типов.

То, что вы ищете, — это протокол с соответствующим типом. Связанный тип в протоколе означает, что соответствующий тип может решить, какой конкретный тип использовать вместо связанного типа, следовательно, позволяя вам использовать разные связанные типы в разных соответствующих классах.

 protocol MyProtocol {
    associatedtype MyType: MainItem
    func myFunc() -> MyType
}

class ClassA: MyProtocol {
    func myFunc() -> Item1 {
        return Item1()
    }
}

class ClassB: MyProtocol {
    func myFunc() -> Item2 {
        return Item2()
    }
}
  

Комментарии:

1. Большое вам спасибо. Это то, что я искал!