解析时避免使用 switch 语句
Avoid the usage of a switch statement when parsing
我一直在努力开发一个代码来避免大的 switch 语句。
基本上我得到了一组元组作为输入,现在我想根据元组中指定的类型实例化适当的 class(元组的第一个元素 - 例如(“Apple”, ...)).
目前我通过使用 switch 语句解决了我的问题,但是如果将来 classes 的数量增加,这是一个非常糟糕的主意。有什么优雅的方法可以规避这个问题吗?
谢谢!
class Apple {
var color = ""
}
class Banana {
var isTasty = false
}
let input = [("Apple", "green"),("Banana", "TRUE")]
for (type, value) in input {
switch type {
case "Apple":
Apple()
case "Banana":
Banana()
default:
print(value)
}
}
看看这个,
// Parent Class to group them
class Fruit {
var baseValue: Any
required init(_ this: Any) {
baseValue = this
(self as? Apple)?.color = this as! String
(self as? Banana)?.isTasty = this as! Bool
// You can add more subclasses here
}
}
class Apple: Fruit, Equatable {
var color = ""
func hash(into hasher: inout Hasher) {
hasher.combine(color)
}
static func == (lhs: Apple, rhs: Apple) -> Bool {
return lhs.color == rhs.color
}
}
class Banana: Fruit, Equatable {
var isTasty = false
func hash(into hasher: inout Hasher) {
hasher.combine(isTasty)
}
static func == (lhs: Banana, rhs: Banana) -> Bool {
return lhs.isTasty == rhs.isTasty
}
}
有点烦人的是它们必须符合 Fruit、Hashable 和 Equatable。但它让你这样做,这回答了你的问题:
let input: [(Fruit.Type,Any)] = [(Apple.self, "green"),(Banana.self, true)]
for (type, value) in input {
// Now you don't need that switch statement
let foo = type.init(value)
// Now you can use `as?` to find out what it is
print((foo as? Banana)?.isTasty)
// See, it prints `nil` first, then `Optional(true)` next.
// Which is how we want it to run
}
不过,我认为我们可以做得更好。
enum Fruit {
case apple(color: String)
case banana(isTasty: Bool)
}
let input: [Fruit] = [.apple(color: "red"), .banana(isTasty: true)]
好多了。
我一直在努力开发一个代码来避免大的 switch 语句。
基本上我得到了一组元组作为输入,现在我想根据元组中指定的类型实例化适当的 class(元组的第一个元素 - 例如(“Apple”, ...)).
目前我通过使用 switch 语句解决了我的问题,但是如果将来 classes 的数量增加,这是一个非常糟糕的主意。有什么优雅的方法可以规避这个问题吗?
谢谢!
class Apple {
var color = ""
}
class Banana {
var isTasty = false
}
let input = [("Apple", "green"),("Banana", "TRUE")]
for (type, value) in input {
switch type {
case "Apple":
Apple()
case "Banana":
Banana()
default:
print(value)
}
}
看看这个,
// Parent Class to group them
class Fruit {
var baseValue: Any
required init(_ this: Any) {
baseValue = this
(self as? Apple)?.color = this as! String
(self as? Banana)?.isTasty = this as! Bool
// You can add more subclasses here
}
}
class Apple: Fruit, Equatable {
var color = ""
func hash(into hasher: inout Hasher) {
hasher.combine(color)
}
static func == (lhs: Apple, rhs: Apple) -> Bool {
return lhs.color == rhs.color
}
}
class Banana: Fruit, Equatable {
var isTasty = false
func hash(into hasher: inout Hasher) {
hasher.combine(isTasty)
}
static func == (lhs: Banana, rhs: Banana) -> Bool {
return lhs.isTasty == rhs.isTasty
}
}
有点烦人的是它们必须符合 Fruit、Hashable 和 Equatable。但它让你这样做,这回答了你的问题:
let input: [(Fruit.Type,Any)] = [(Apple.self, "green"),(Banana.self, true)]
for (type, value) in input {
// Now you don't need that switch statement
let foo = type.init(value)
// Now you can use `as?` to find out what it is
print((foo as? Banana)?.isTasty)
// See, it prints `nil` first, then `Optional(true)` next.
// Which is how we want it to run
}
不过,我认为我们可以做得更好。
enum Fruit {
case apple(color: String)
case banana(isTasty: Bool)
}
let input: [Fruit] = [.apple(color: "red"), .banana(isTasty: true)]
好多了。