簡體   English   中英

Swift泛型數組

[英]Swift array of generics

如何創建泛型數組? 例:

struct Thing<Any> {
}

let intThing = Thing<Int>()
let stringThing = Thing<String>()

// This line doesn't compile
// Cannot convert value of type 'Thing<Int>' to expected type 'Thing'
let things: [Thing] = [intThing, stringThing]

如何聲明任何類型的泛型(如Thing<?>Thing<Any> )?

你可以這樣做:
let things: [Any] = [intThing, stringThing]

Thing是不是有效的類型在它自己的。 Thing<String>是類型, Thing<Int>是其他類型,您不能在數組中混合使用其他類型。

您是否注意到甚至let things: [Thing]無法編譯?

我認為您可能想做的事將是使用帶有關聯值的枚舉的更好的服務器。


struct MyStruct<T> {

    let property: T
    init(property: T) {
        self.property = property
    }
}

enum Thing {
    case int(Int)
    case string(String)
    case intStruct(MyStruct<Int>)
}

// creation
let myInt = Thing.int(2)
let myString = Thing.string("string")
let myIntStruct = Thing.intStruct(MyStruct<Int>(property: 3))

// down side is that you need a 'case' clause to retrieve the data
switch myIntStruct {
case let .int(value):
    print("have a int: \(value)")
case let .string(value):
    print("have a string: \(value)")
case let.intStruct(value):
    print("have a intStruct\(value)")
}

// An array of Thing
let things: [Thing] = [myInt, myString, myIntStruct]

關於提前枚舉技巧的好文章
在該文件有關包裝的plist數據到一個單一的結構中,存在使用了的EntityType枚舉的。


您可以將任何內容與枚舉值相關聯,但它必須是完全限定的類型。 因此,您不能使用MyStruct,因為它不完全合格,您需要使用MyStruct<Int>來完全合格。 這意味着您需要為要與MyStruct一起使用的每個泛型類型創建一個案例。

這是您使用通用方法所能做到的。
我不確定您要做什么。 但是,如果要實現某種依賴於在T上操作但不使用T作為輸入或輸出的方法的多態,則應使Thing實現一個協議並對該協議進行數組,然后在該協議上調用多態方法協議。

您可以使用一個枚舉

enum Thing {
    case Text(String)
    case Integer(Int)
}

現在您可以創建一個包含字符串或整數的事物

let thingWithText = Thing.Text("Hello world")
let thingWithInt = Thing.Integer(123)

您可以將它們放入Thing(s)數組中(不涉及泛型)。

let things = [thingWithText, thingWithInt]

最后,您可以通過這種方式處理數組中的值

things.forEach { (thing) -> () in
    switch thing {
    case .Text(let text): print(text)
    case .Integer(let integer): print(integer)
    }
}

這會有所幫助

protocol Six {}
struct Thing<Any> :Six {}

let intThing = Thing<Int>()
let stringThing = Thing<String>()
let things: [Six] = [intThing, stringThing]

您可以使用包含所有要使用的相關屬性和功能的協議:

protocol ThingProtocol {
    func doSomething()

    // if you want to expose generic functions/properties
    // use functions/properties which have the most specific type
    // for Thing<T: AProtocol> it should be `var anyValue: AProtocol { get }`
    // here: `Any` since T in Thing<T> can be anything
    var anyValue: Any { get }
}

struct Thing<T>: ThingProtocol {
    var value: T

    // ThingProtocol implementation
    var anyValue: Any { return value as Any }
    func doSomething() { ... }
}

let intThing = Thing<Int>(value: 42)
let stringThing = Thing<String>(value: "101010")

let things: [ThingProtocol] = [intThing, stringThing]

things[0].doSomething()
things[0].anyValue // returns a value of type Any

// you cannot call `value` since it is not specified in the protocol. If you do it, it would result in an error in `Thing<T>`
things[0].value // error

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM