我正在尝试在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)
我该怎么做?我在这里有点受阻,所以欢迎所有的想法。
答案 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>()