以下回答显示一个可能解决方案;可能不是推荐的一个(但对未来这个问题的读者可能会感兴趣)。
如果您有大量这都属于一个比较有限数量的不同类型的的属性,你可以使用你的结构实例的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,谢谢!我知道协议扩展如何工作,但我不知道如何将它用于我的问题。 –