Swift 问题:如果非可选变量是协议类型,我们如何在 if else 块中初始化它?
Swift question: how can we init an non-optional variable in a if else block if it's of protocol type?
在Swift中,我们可以不立即初始化非可选变量,而是稍后在 if else 块中初始化,例如:
let result: Bool
if something {
result = computeSomething()
} else {
result = computeSomethingElse()
}
但是如果我的变量是协议类型呢? (在我的示例中,我想使用作为协议的 GraphQLMutation 来执行此操作):
let mutation: GraphQLMutation
if something {
mutation = StartMutation()
} else {
mutation = StopMutation()
}
self.graphQLDataSource.set(mutation: mutation)
Swift 编译器错误说:
Protocol 'GraphQLMutation' can only be used as a generic constraint because it has Self or associated type requirements
有没有办法做到这一点并避免代码重复?
它确实适用于协议:
protocol Foo {}
struct A: Foo {}
class B: Foo {}
let x: Foo
if Bool.random() {
x = A()
} else {
x = B()
}
它只是不适用于具有关联类型的协议。您只能在通用函数中使用它。这是一些展示它的代码:
protocol Foo {
associatedtype T
}
struct A: Foo {
typealias T = Int
}
class B: Foo {
typealias T = String
}
func x<Foo>(_ test: Bool) -> Foo? {
let x: Foo?
if test {
x = A() as? Foo
} else {
x = B() as? Foo
}
return x
}
let a1: A? = x(true) // => A
let a2: A? = x(false) // => nil
let b1: B? = x(true) // => nil
let b2: B? = x(false) // => B
对于 a1
我们得到了一个 A
的实例,因为转换 A() as? Foo
有效,因为它有一个 Foo
类型和关联类型Int
由 let a1: A?
.
要求
对于 a2
我们得到 nil,因为转换 B() as? Foo
失败,因为它不能被转换为 Foo
与所需的关联类型 Int
let a2: A?
.
对于 b1
我们得到 nil,因为转换 A() as? Foo
失败,因为它不能被转换为 Foo
与所需的关联类型 String
let b1: B?
.
对于 b2
我们得到了一个 B
的实例,因为转换 B() as? Foo
有效,因为它有一个 Foo
类型和关联类型String
由 let b2: B?
.
要求
在Swift中,我们可以不立即初始化非可选变量,而是稍后在 if else 块中初始化,例如:
let result: Bool
if something {
result = computeSomething()
} else {
result = computeSomethingElse()
}
但是如果我的变量是协议类型呢? (在我的示例中,我想使用作为协议的 GraphQLMutation 来执行此操作):
let mutation: GraphQLMutation
if something {
mutation = StartMutation()
} else {
mutation = StopMutation()
}
self.graphQLDataSource.set(mutation: mutation)
Swift 编译器错误说:
Protocol 'GraphQLMutation' can only be used as a generic constraint because it has Self or associated type requirements
有没有办法做到这一点并避免代码重复?
它确实适用于协议:
protocol Foo {}
struct A: Foo {}
class B: Foo {}
let x: Foo
if Bool.random() {
x = A()
} else {
x = B()
}
它只是不适用于具有关联类型的协议。您只能在通用函数中使用它。这是一些展示它的代码:
protocol Foo {
associatedtype T
}
struct A: Foo {
typealias T = Int
}
class B: Foo {
typealias T = String
}
func x<Foo>(_ test: Bool) -> Foo? {
let x: Foo?
if test {
x = A() as? Foo
} else {
x = B() as? Foo
}
return x
}
let a1: A? = x(true) // => A
let a2: A? = x(false) // => nil
let b1: B? = x(true) // => nil
let b2: B? = x(false) // => B
对于
a1
我们得到了一个A
的实例,因为转换A() as? Foo
有效,因为它有一个Foo
类型和关联类型Int
由let a1: A?
. 要求
对于
a2
我们得到 nil,因为转换B() as? Foo
失败,因为它不能被转换为Foo
与所需的关联类型Int
let a2: A?
.对于
b1
我们得到 nil,因为转换A() as? Foo
失败,因为它不能被转换为Foo
与所需的关联类型String
let b1: B?
.对于
b2
我们得到了一个B
的实例,因为转换B() as? Foo
有效,因为它有一个Foo
类型和关联类型String
由let b2: B?
. 要求