试图在swift

时间:2016-05-03 17:45:59

标签: swift generics

我正在尝试在Swift中创建一个通用类,Xcode 7.3(所以Swift 2.2),但我似乎无法通过编译器:

protocol Struct1Protocol {
}

struct Struct1 {
    var name1: String
}

protocol Struct2Protocol {
}

struct Struct2: Struct2Protocol {
    var name2: String
}

class StructDependent<T> {
    func setupFrom<T:Struct1Protocol>(value: T) {
        print("we want to setup StructDependent with struct 1")
    }

    func setupFrom<T:Struct2Protocol>(value: T) {
        print("we want to setup StructDependent with struct 2")
    }
}

class A<T> {
    func test(value: T) {
        let structInstance = StructDependent<T>()
        // this gives a compiler error:
        // Cannot invoke 'setupFrom' with an argument list of type '(T)'
        structInstance.setupFrom(value)
    }
}

我们的想法是拥有一个可以从不同结构设置的StructDependent。如果类已使用兼容的结构体进行实例化,则类A应该能够调用setupFrom。像这样:

let a = A<Struct1>()
let v = Struct1(name1: "")
a.test(v)

我该怎么做?我在这里有点受阻,所以欢迎所有的想法。

2 个答案:

答案 0 :(得分:3)

在我看来,你过分思考这个问题。我会对案件采取更为简单的观点,并且完全没有泛化;相反,我们只使用一个协议作为两种结构的超类型(正如我们在结构类是类时使用超类一样):

protocol StructProtocol {
    var name : String {get set}
    func setup()
}

struct Struct1 : StructProtocol{
    var name: String
    func setup() {}
}

struct Struct2 : StructProtocol {
    var name: String
    func setup() {}
}

class StructDependent {
    func setup(s:StructProtocol) {
        s.setup() // or not, I don't care...
        // or you could just switch on the type, e.g.:
        switch s {
        case is Struct1: // ...
        case is Struct2: // ...
        default: break
        }
    }
}

class A {
    func test(value: StructProtocol) {
        let structInstance = StructDependent()
        structInstance.setup(value)
    }
}

如果StructDependent 本身确实需要根据调用的setup做不同的事情,它可以切换实际类型。但是第一种方式会更好,我们只是用它自己的方式调用Struct1和Struct2都知道怎么做的东西。

答案 1 :(得分:1)

您需要在泛型类型上设置类型约束。 您可以为此约束使用全包协议。

protocol StructProtocol {
}

protocol Struct1Protocol: StructProtocol {
}

struct Struct1: Struct1Protocol {
var name1: String
}

 protocol Struct2Protocol: StructProtocol {
}

struct Struct2: Struct2Protocol {
var name2: String
}



class StructDependent<T> {
func setupFrom<T:Struct1Protocol>(value: T) {
    print("we want to setup StructDependent with struct 1")
}

func setupFrom<T:Struct2Protocol>(value: T) {
    print("we want to setup StructDependent with struct 2")
}
}

class A<T: Struct1Protocol> {
func test(value: T) {
    let structInstance = StructDependent<T>()
    // this gives a compiler error:
    // Cannot invoke 'setupFrom' with an argument list of type '(T)'
    structInstance.setupFrom(value)
}
}

let a = A<Struct1>()