swift - Swift 问题:如果 if else 块是协议类型,我们如何初始化一个非可选变量?
问题描述
在 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
我们得到了一个 as 的实例,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
我们得到了一个 as 的实例,B
因为B() as? Foo
它的类型为,Foo
并且具有.String
let b2: B?
推荐阅读
- lua - GMOD - Cam3D2D 纹理矩形上的奇怪纹理故障
- visual-studio - 错误:无法启动并输出:无法创建托管进程... c# interactive
- flutter - 包括小部件内 url 的内容
- css - 错误:无效的 CSS,同时将 SASS 转换为 CSS
- postgresql - 如何在postgresql中通过组合计算并发事件的频率/计数?
- php - 如何使用php解析html以获取数组中的值
- pandas - 使用 Pandas 计算两列中匹配记录的百分比
- php - 如何修改此代码以使用良好实践?(接口、特征、抽象类)
- reactjs - 如何在 React(Ant Design v4) 中使用 DatePicker(moment.js) 更改日期格式和时区?
- android - Android:在 Recyclerview 中滚动时设置搜索栏可见性