不同的类/结构符合indexOf

时间:2016-02-09 20:56:08

标签: arrays swift

我有两个不同的类/结构,我希望能够使用:

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'

1 个答案:

答案 0 :(得分:0)

问题是Equatable的运算符重载定义是:

func ==(_ lhs: Self, _ rhs: Self) -> Bool

因此它包含在它所操作的对象类型中 - 在您的情况下为FooBar,但不是两者的混合。 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)