Создать словарь общих переменных в Swift - PullRequest
0 голосов
/ 29 мая 2019

Я ищу способ хранения подкласса дженериков в словаре, но у меня проблемы.

В следующем примере я пытаюсь создать словарь объектов, который, как я знаю, будет подклассом Entity<T>.Я успешно храню отдельные экземпляры своих подклассов FloatEntity и StringEntity в типе var Entity, но при попытке сохранить их в словаре типа Dictionary<String, Entity> я получаю сообщение об ошибке.

class Entity<T> {
    var _value: T
    var value: T { get { return _value } set {_value = newValue}}

    init (defaultValue: T) {
        _value = defaultValue
    }
}

class FloatEntity: Entity<Float> {
}

class StringEntity: Entity<String> {
}

func run () {
    let variable1: Entity = FloatEntity (defaultValue: 1)
    let variable2: Entity = StringEntity (defaultValue: "")
    var dictionary: Dictionary<String, Entity> = [
        "One": FloatEntity (defaultValue: 1),
        "Two": StringEntity (defaultValue: ""),
    ]
    print (variable1)
    print (variable2)
    print (dictionary)
}

Ошибка:

Невозможно преобразовать значение типа 'FloatEntitiy' в ожидаемое значение словарного типа 'Entity'

Может кто-нибудь посоветовать, как мне поступитьоб использовании словаря для хранения таких обобщений?

Ответы [ 3 ]

2 голосов
/ 29 мая 2019

variable1 и variable2 не относятся к типу Entity, но на самом деле Entity<Float> и Entity<String> являются двумя не связанными типами. Используйте protocol, чтобы объединить их:

protocol EntityProtocol { }

class Entity<T> : EntityProtocol {
    var _value: T
    var value: T { get { return _value } set {_value = newValue}}

    init (defaultValue: T) {
        _value = defaultValue
    }
}

class FloatEntity: Entity<Float> {
}

class StringEntity: Entity<String> {
}

func run () {
    let variable1: Entity = FloatEntity (defaultValue: 1)
    let variable2: Entity = StringEntity (defaultValue: "")
    var dictionary: Dictionary<String, EntityProtocol> = [
        "One": FloatEntity (defaultValue: 1),
        "Two": StringEntity (defaultValue: ""),
    ]
    print (variable1)
    print (variable2)
    print (dictionary)
}
1 голос
/ 29 мая 2019

Из того, что вы предоставили, это не похоже на хорошее использование универсального.Если идея заключается в том, чтобы хранить значения в словаре, где каждое значение может быть строкой или плавающей точкой, это больше похоже на перечисление со связанными значениями (это код игровой площадки):

enum StringOrFloat {
    case string(String)
    case float(Float)
}
let v1 = StringOrFloat.string("meaning of life")
let v2 = StringOrFloat.float(42)
var d = Dictionary<String,StringOrFloat>()
d["hey"] = v1
d["ho"] = v2

ИВот способ извлечь значение:

if let val = d["hey"] {
    switch val {
    case .string(let s):
        print("it is a string, namely", s)
    case .float(let f):
        print("it is a float, namely", f)
    }
}
0 голосов
/ 29 мая 2019

Обобщения Swift являются инвариантными, поэтому Entity<B> не является подклассом Entity<A>, даже если B будет подклассом A. Поэтому вы не можете хранить те же типы, используя суперкласс Entity в словаре.

Вы можете достичь желаемого, используя AnyObject в качестве значения словаря, например с этим кодом: -

var dictionary: Dictionary<String, AnyObject> = [
  "One": FloatEntity (defaultValue: 1),
  "Two": FloatEntity (defaultValue: 2),
]

Я не думаю, что из этого можно извлечь Entity с удаленным шрифтом (рад, что его исправили). Но вы могли бы сделать что-то вроде этого: -

let v = dictionary["One"]
if let v1 = v as? FloatEntity
{
  ...
}
...