我有两个不同的类/结构,我希望能够使用:
let index = [T].indexOf(U)
游乐场的一些示例数据:
struct Foo: Hashable {
let name: String
var hashValue: Int { return name.hashValue }
}
struct Bar: Hashable {
let name: String
var hashValue: Int { return name.hashValue }
}
func ==(lhs: Foo, rhs: Foo) -> Bool { return lhs.name == rhs.name }
func ==(lhs: Bar, rhs: Bar) -> Bool { return lhs.name == rhs.name }
func ==(lhs: Bar, rhs: Foo) -> Bool { return lhs.name == rhs.name }
尝试:
let test1 = Foo(name: "John")
let test2 = Foo(name: "Amy")
let test3 = Bar(name: "Mary")
let test4 = Bar(name: "John")
let arrays = [test1, test2]
let result = arrays.indexOf(test3) // cannot convert value of type 'Bar' to expected argument type 'Foo'
我应该只使用协议吗?
使用协议:
protocol Names {
var name: String { get set }
}
extension Equatable where Self: Names { }
struct Foo: Names { var name: String }
struct Bar: Names { var name: String }
func ==<T: Names>(lhs: T, rhs: T) -> Bool {
return lhs.name == rhs.name
}
尝试:
let arrays: [Names] = [test1, test2]
let result = arrays.indexOf(test2) // cannot convert value of type 'Foo' to expected argument type '@noescape (Names) throws -> Bool'
和
protocol Names: Equatable {
var name: String { get set }
}
let arrays: [Foo] = [test1, test2]
let result = arrays.indexOf(test3) // cannot convert value of type 'Bar' to expected argument type 'Foo'
答案 0 :(得分:0)
问题是Equatable
的运算符重载定义是:
func ==(_ lhs: Self, _ rhs: Self) -> Bool
因此它包含在它所操作的对象类型中 - 在您的情况下为Foo
或Bar
,但不是两者的混合。 Equatable
永远不会使用以下声明:
func ==(lhs: Bar, rhs: Foo) -> Bool { return lhs.name == rhs.name }
您可以将结构更改为子类共同祖先的类吗?沿着:
class FooBar: Hashable {
var name: String!
var hashValue: Int { return name.hashValue }
init() { }
}
class Foo: FooBar {
}
class Bar: FooBar {
}
func ==(lhs: FooBar, rhs: FooBar) -> Bool { return lhs.name == rhs.name }
var test1 = Foo(); test1.name = "John"
var test2 = Foo(); test2.name = "Amy"
var test3 = Bar(); test3.name = "Mary"
var test4 = Bar(); test4.name = "John"
let arrays: [FooBar] = [test1, test2]
let result = arrays.indexOf(test4)
print(result)