我正在尝试制作一个简单的游戏实现。所以每场比赛都有一个正确的答案。 Answer 可以是 Int 或 String。所以我的代码是:
protocol Answer {}
extension Int: Answer {}
extension String: Answer {}
protocol CorrectAnswer {
var correctAnswer: Answer { get }
}
我有一个游戏需要的协议(protocol):
protocol GameDescriber {
var name: String { get }
var description: String { get }
var points: Int { get }
}
以及 Game 结构体的实现:
struct Game: GameDescriber, Equatable, CorrectAnswer {
var correctAnswer: Answer
var name: String
var description: String
var points: Int
static func ==(_ lhs: Game, _ rhs:Game) -> Bool {
if let _ = lhs.correctAnswer as? String, let _ = rhs.correctAnswer as? Int {
return false
}
if let _ = lhs.correctAnswer as? Int, let _ = rhs.correctAnswer as? String {
return false
}
if let lhsInt = lhs.correctAnswer as? Int, let rhsInt = rhs.correctAnswer as? Int {
if lhsInt != rhsInt {
return false
}
}
if let lhsString = lhs.correctAnswer as? String, let rhsString = rhs.correctAnswer as? String {
if lhsString != rhsString {
return false
}
}
return lhs.description == rhs.description &&
lhs.name == rhs.name &&
lhs.points == rhs.points
}
}
如果我想添加另一种 Answer 类型(假设是 Ints 数组),我必须这样做:
extension Array: Answer where Element == Int {}
但令我困扰的是 Equatable func 的实现 == 我必须涵盖这种情况以及可能的其他情况。这让我很戏剧化:)
是否有针对此问题的解决方案,能否以更优雅和通用的方式完成?
最佳答案
首先请注意,==
的实现可以简化为
static func ==(_ lhs: Game, _ rhs:Game) -> Bool {
switch (lhs.correctAnswer, rhs.correctAnswer) {
case (let lhsInt as Int, let rhsInt as Int):
if lhsInt != rhsInt {
return false
}
case (let lhsString as String, let rhsString as String):
if lhsString != rhsString {
return false
}
default:
return false
}
return lhs.description == rhs.description &&
lhs.name == rhs.name &&
lhs.points == rhs.points
}
这样添加另一种答案类型就意味着添加一个额外的 案例。
问题是编译器无法验证所有可能的
答案类型在你的 ==
函数中处理,所以这种方法
很容易出错。
我实际上会做的是使用 enum Answer
而不是
协议(protocol),并使 that Equatable
:
enum Answer: Equatable {
case int(Int)
case string(String)
}
请注意,您不必实现 ==
。从 Swift 4.1 开始,
编译器自动合成,见
SE-0185 Synthesizing Equatable and Hashable conformance .
现在 Game
简化为
struct Game: GameDescriber, Equatable, CorrectAnswer {
var correctAnswer: Answer
var name: String
var description: String
var points: Int
}
编译器也合成 ==
,默认实现比较所有存储的属性是否相等。
添加另一个答案类型只需将另一个案例添加到 枚举:
enum Answer: Equatable {
case int(Int)
case string(String)
case intArray([Int])
}
没有任何额外的代码。
关于swift - swift 中的平等协议(protocol),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50774154/