swift - 如何在 switch 语句中(同时)键入匹配和解包可选值?
问题描述
有没有办法在一个案例中结合类型匹配和展开可选值?
在以下操场代码中,有三个循环:
循环 A用于if let
匹配类型并同时解开可选值。
在循环 B中,我用语句替换了if let
's 。switch
但是,我正在使用where
并检查nil
,然后从这一点开始强制解开我的值。
我想知道是否有类似于循环 C的方法来解包这些值,以便我可以像在循环 A 中那样使用这些新的非可选变量。
import Foundation
// Setup
protocol MyObjects {}
struct MyTopic: MyObjects {
let name: String?
}
struct MyQuestion: MyObjects {
let text: String?
let topic: String?
}
let topicOrQuestions: [MyObjects] = [
MyQuestion(text: "questionA", topic: "topicA"),
MyTopic(name: "topicA"),
MyTopic(name: "topicB"),
MyTopic(name: nil)
]
// Loop A:
for topicOrQuestion in topicOrQuestions {
if let name = (topicOrQuestion as? MyTopic)?.name {
print(name)
} else if let text = (topicOrQuestion as? MyQuestion)?.text, let topic = (topicOrQuestion as? MyQuestion)?.topic {
print(text, topic)
} else {
print("Error: wrong type or nil value")
}
}
// Loop B:
for topicOrQuestion in topicOrQuestions {
switch topicOrQuestion {
case let topic as MyTopic where topic.name != nil:
print(topic.name!)
case let question as MyQuestion where question.text != nil && question.topic != nil:
print(question.text!, question.topic!)
default:
print("Error: wrong type or nil value")
}
}
// Loop C (doesn't work):
for topicOrQuestion in topicOrQuestions {
switch topicOrQuestion {
case let name as MyTopic.name: // <-- Is it possible to unwrap the values here directly similar to the if let's in Loop A?
print(name)
case let text as MyQuestion.text, let topic as MyQuestion.topic:
print(text, topic)
default:
print("Error: wrong type or nil value")
}
}
/*
Current output from Loop A and B and expected output from Loop C:
questionA topicA
topicA
topicB
Error: wrong type or nil value
*/
解决方案
我不认为你将能够在一个案例中进行投射和解包,但有了这个扩展,至少你Loop A
会不那么冗长:
extension MyObjects {
subscript<T: MyObjects, V>(topicOrQuestion keypath: (T) -> V) -> V? {
get {
guard let root = self as? T else { return nil }
return keypath(root)
}
}
}
你也可以写这个循环:
for topicOrQuestion in topicOrQuestions {
if let topicName = topicOrQuestion[topicOrQuestion: \MyTopic.name] as? String {
print(topicName)
}
if let questionText = topicOrQuestion[topicOrQuestion: \MyQuestion.text] as? String ,
let questionTopic = topicOrQuestion[topicOrQuestion: \MyQuestion.topic] as? String {
print(questionText, questionTopic)
}
}
// questionA topicA
// topicA
// topicB
推荐阅读
- nginx - “/opt/eds/web/html”的目录索引被禁止
- groovy - Groovy 脚本中的错误:当前范围已包含一个变量
- c# - C# 为 System.Uri 属性分配默认值
- android - 如何与私人测试版用户一起发布
- angular - 如何在角度 html 文件中使用 (toLowerCase()) 类似的方法?
- java - 无需重新启动服务器即可重新加载密钥库
- python - 数据未与日期时间正确分组
- python - 动态 GStreamer 管道不可搜索
- scala - 什么时候有 2.13 的 sbt 版本?
- c++ - std::optional::emplace() 默认构造一个可选在clang中不起作用?