Приведите SomeType <Protocol>к SomeType <ProtocolImpl>в Swift - PullRequest
0 голосов
/ 26 февраля 2020

Я сейчас экспериментирую с Generics в Swift и столкнулся с некоторой проблемой с приведением некоторых типов, таких как SomeType<Protocol> к SomeType<ProtocolImpl>. Таким образом, в основном у меня есть некоторый тип, который принимает параметр generic c, который обрабатывается как протокол и который позднее приводится к более конкретному типу. Мой вопрос, если это невозможно сделать?

/// 'dict' is of type [String: SomeType<Protocol>]
if let element = dict["str"], // 'element' here is of type SomeType<Protocol>
   let castedElement = element as? SomeType<ProtocolImpl> { // This is always false
    return castedElement // Here I want to return castedElement with type SomeType<ProtocolImpl>
}

Есть ли способ заставить этот актерский состав работать? Я уже работаю над другим решением для моей проблемы, но мне все еще интересно, есть ли способ как-то сделать эту работу.

Редактировать: потому что @jtbandes хотел пример, который он может вставить куда-нибудь, здесь:

class SomeType<T> {
    let value: T

    init(value: T) {
        self.value = value
    }
}

protocol Protocol {}

class ProtocolImpl: Protocol {}

var dict: [String: SomeType<Protocol>] = ["str": SomeType(value: ProtocolImpl())]

if let element = dict["str"],
   let castedElement = element as? SomeType<ProtocolImpl> {
    print(castedElement.value) // I want to get here
}

Ответы [ 2 ]

1 голос
/ 01 марта 2020

Короче говоря, дженерики в Swift не являются ковариантными, что означает, что SomeType< ProtocolImpl> не является конвертируемым SomeType<Protocol>, даже если ProtocolImpl соответствует Protocol. Таким образом, прямой ответ на ваш вопрос таков: в настоящее время это невозможно в Swift.

Однако вы можете спросить себя, зачем вам в первую очередь удручать. Поскольку вы храните экземпляры в контейнере, поведение polymorphi c может оказаться более подходящим. Вы можете объявить функциональность, к которой вам необходимо получить доступ, как часть протокола, и доступ через интерфейс протокола. Таким образом, вам не нужно знать, какая конкретная реализация скрыта, что является одной из основных причин использования протокола.

0 голосов
/ 29 февраля 2020

Мне трудно сказать, чего вы пытаетесь достичь из этого вопроса. Тем не менее, может быть, ниже поможет вам.

class SomeType<T>: Protocol { // Maybe SomeType IS your ProtoImpl?
    let value: T

    init(value: T) {
        self.value = value
    }
}

protocol Protocol {}

//class ProtocolImpl: Protocol {}

//var dict: [String: SomeType<Protocol>] = ["str": SomeType(value: ProtocolImpl())]
var dict: [String: Protocol] = ["str1": SomeType<String>(value: "Some Type"),
                                "str2": SomeType<Int>(value: 1)
                            ]

if let castedElement = dict["str1"] as? SomeType<String> {
    print(castedElement.value) // --> "Some Type"
}

if let castedElement = dict["str2"] as? SomeType<Int> {
    print(castedElement.value) // --> "1"
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...