以下回答顯示一個可能解決方案;可能不是推薦的一個(但對未來這個問題的讀者可能會感興趣)。
如果您有大量這都屬於一個比較有限數量的不同類型的的屬性,你可以使用你的結構實例的Mirror
和迭代在結構的屬性;對於每個嘗試轉換到不同類型的,您知道您的屬性爲。
我已經編輯了以前的答案(的東西,我相信頗多整潔),看下面的WWDC 2015年會議結束後(感謝獅子座Dabus!):
我會離開這個答案底部的初步回答爲好,因爲它顯示了一種替代,面向協議的方法少,利用這一Mirror
解決方案。
Mirror
&面向協議的解決方案:
/* Let a heterogeneous protocol act as "pseudo-generic" type
for the different (property) types in 'SuperStruct' */
protocol MyGenericType {
func isEqualTo(other: MyGenericType) -> Bool
}
extension MyGenericType where Self : Equatable {
func isEqualTo(other: MyGenericType) -> Bool {
if let o = other as? Self { return self == o }
return false
}
}
/* Extend types that appear in 'SuperStruct' to MyGenericType */
extension Int : MyGenericType {}
extension String : MyGenericType {}
extension Float : MyGenericType {}
// ...
/* Finally, 'SuperStruct' conformance to Equatable */
func ==(lhs: SuperStruct, rhs: SuperStruct) -> Bool {
let mLhs = Mirror(reflecting: lhs).children.filter { $0.label != nil }
let mRhs = Mirror(reflecting: rhs).children.filter { $0.label != nil }
for i in 0..<mLhs.count {
guard let valLhs = mLhs[i].value as? MyGenericType, valRhs = mRhs[i].value as? MyGenericType else {
print("Invalid: Properties 'lhs.\(mLhs[i].label!)' and/or 'rhs.\(mRhs[i].label!)' are not of 'MyGenericType' types.")
return false
}
if !valLhs.isEqualTo(valRhs) {
return false
}
}
return true
}
實例:
/* Example */
var a = SuperStruct()
var b = SuperStruct()
a == b // true
a.field1 = 2
a == b // false
b.field1 = 2
b.field2 = "Foo"
a.field2 = "Foo"
a == b // true
上一頁Mirror
溶液:
/* 'SuperStruct' conformance to Equatable */
func ==(lhs: SuperStruct, rhs: SuperStruct) -> Bool {
let mLhs = Mirror(reflecting: lhs).children.filter { $0.label != nil }
let mRhs = Mirror(reflecting: rhs).children.filter { $0.label != nil }
for i in 0..<mLhs.count {
switch mLhs[i].value {
case let valLhs as Int:
guard let valRhs = mRhs[i].value as? Int where valRhs == valLhs else {
return false
}
case let valLhs as String:
guard let valRhs = mRhs[i].value as? String where valRhs == valLhs else {
return false
}
case let valLhs as Float:
guard let valRhs = mRhs[i].value as? Float where valRhs == valLhs else {
return false
}
/* ... extend with one case for each type
that appear in 'SuperStruct' */
case _ : return false
}
}
return true
}
用法示例:
/* Example */
var a = SuperStruct()
var b = SuperStruct()
a == b // true
a.field1 = 2
a == b // false
b.field1 = 2
b.field2 = "Foo"
a.field2 = "Foo"
a == b // true
你應該看看協議擴展。 WWDC 2015 Session 408. http://devstreaming.apple.com/videos/wwdc/2015/408509vyudbqvts/408/408_hd_protocoloriented_programming_in_swift.mp4?dl=1 –
你會多麼努力編寫一個小幫手來解析一段代碼並生成所需的方法?在上面添加bean的版本,以跟蹤可能需要更新的代碼,並且你很好。 –
Leo Dabus,謝謝!我知道協議擴展如何工作,但我不知道如何將它用於我的問題。 –