这样的事情:
protocol A {}
protocol B {}
func newObject<T: A, B>(flag: Bool) -> T {
if flag {
var aaa: A
return aaa
} else {
var bbb: B
return bbb
}
}
我收到错误:
'A' is not convertible to 'T'
答案 0 :(得分:5)
您正在寻找的类型称为“Either”,并且可以使用枚举在Swift中轻松创建。例如:
protocol A {}
protocol B {}
enum AorB {
case IsA(A)
case IsB(B)
}
func newObject(flag: Bool) -> AorB {
if flag {
return .IsA(...create an A...)
} else {
return .IsB(...create a B...)
}
}
在创建这样的东西时,你应该仔细考虑你的类型的真正含义。什么是AorB
真的?可以通过创建Either<Left,Right>
(在某些语言中常见)来为此创建通用持有者,但在许多情况下,有更好的名称可以提供给此枚举(如Success
和{{1 }}或Failure
和Local
)。当您的类型干净利落时,您的程序更可能是正确的。
请注意,Swift确实支持返回重载。例如:
Remote
但是,这应该谨慎使用,因为对于调用者来说这可能很尴尬(当然,传递一个标志......)。对于可能以类型推理工作的方式链接的函数更有意义。在我看来,如果你有一个在两个行为之间翻转的布尔值,你真正拥有的是两个函数,你应该强烈地倾向于为它们命名不同的东西。
这是一个完整的工作示例。不幸的typealias A = String
typealias B = Int
func newObject() -> A {
return "a"
}
func newObject() -> B {
return 1
}
let x:A = newObject()
类型是Beta5的解决方法。编译器尚未实现在枚举中存储任意大小的通用对象的能力。它必须在编译时知道大小。所以我们用Box
得到它,它有一个已知的大小,因为它只有一个Box
(这对我们来说真的是拳击)。通过Swift的v1,您应该能够完全删除[]
包装器。
Box
答案 1 :(得分:0)
您收到上面的错误消息,因为您的返回值仅符合协议A或协议B.但是,您的签名表明返回类型符合两者。
您的签名:
func newObject<T: A, B>(flag: Bool) -> T
可以读作符合A和B的返回类型。
您实际需要的是返回类型重载。从我的理解不存在。但是,您可以通过返回两个选项作为元组来解决这个问题。以下是如何执行此操作的简短示例。
protocol a{}
protocol b{}
class AnAClass : a{
var name = "A Class"
}
class AnBClass : b{
var name = "B Class"
}
func newObject(flag: Bool) -> (a?, b?){
if flag{
var aaa: a? = AnAClass()
return (aaa, nil)
} else {
var bbb: b? = AnBClass()
return (nil, bbb)
}
}
var tuple = newObject(false)
if let anA = tuple.0 {
println("We have an A")
} else if let anB = tuple.1{
println("We have a B");
} else {
println("Nothing");
}
我说实话,我不认为上面看起来很干净。我建议一个替代方案,但我不完全确定你要解决的问题。