2016-11-21 110 views
3
import Foundation 

struct NotEquable {} 

struct Box<T> { 
    let id: Int 
    let value: T 
} 

extension Box: Equatable { 
    static func ==<T>(lhs: Box<T>, rhs: Box<T>) -> Bool { 
     return lhs.id == rhs.id 
    } 

    static func ==<T: Equatable>(lhs: Box<T>, rhs: Box<T>) -> Bool { 
     return lhs.id == rhs.id && lhs.value == rhs.value 
    } 
} 

infix operator ====: AdditionPrecedence 
public protocol OperatorEqual { 
    static func ====(lhs: Self, rhs: Self) -> Bool 
} 

extension Box: OperatorEqual { 
    static func ====<T>(lhs: Box<T>, rhs: Box<T>) -> Bool { 
     return lhs.id == rhs.id 
    } 

    static func ====<T: Equatable>(lhs: Box<T>, rhs: Box<T>) -> Bool { 
     return lhs.id == rhs.id && lhs.value == rhs.value 
    } 
} 

public protocol MethodStyleEquatable { 
    static func equal(lhs: Self, rhs: Self) -> Bool 
} 

extension Box: MethodStyleEquatable { 
    static func equal<T>(lhs: Box<T>, rhs: Box<T>) -> Bool { 
     return lhs.id == rhs.id 
    } 

    static func equal<T: Equatable>(lhs: Box<T>, rhs: Box<T>) -> Bool { 
     return lhs.id == rhs.id && lhs.value == rhs.value 
    } 
} 

func freeEqual<T>(lhs: Box<T>, rhs: Box<T>) -> Bool { 
    return lhs.id == rhs.id 
} 

func freeEqual<T: Equatable>(lhs: Box<T>, rhs: Box<T>) -> Bool { 
    return lhs.id == rhs.id && lhs.value == rhs.value 
} 

let a = Box(id: 1, value: 1) 
let b = Box(id: 1, value: 2) 
a == b 
a ==== b 
freeEqual(lhs: a, rhs: b) 
Box<Int>.equal(lhs: a, rhs: b) 

let c = Box(id: 1, value: NotEquable()) 
let d = Box(id: 1, value: NotEquable()) 
c == d 
c ==== d 
freeEqual(lhs: c, rhs: d) 
Box<NotEquable>.equal(lhs: c, rhs: d) 

上泛型结构实现Equatable在上面的代码奇怪的行为,有4个实施Equatable的:默认实现,运营商定制风格,方法和风格的自由函数形式。我发现在默认或自定义情况下使用操作符风格总是调用等价函数的通用版本。另一方面,使用方法或自由功能样式将根据T调用正确的版本,符合Equatable或不符合。它是一个错误,或者我如何使通用结构符合Equatable正确。在斯威夫特

回答

4

您正在将类的泛型参数混淆为相等函数的泛型参数。由于写的,你的代码是相同的:

struct Box<T1> { 
    let id: Int 
    let value: T1 
} 

extension Box: Equatable { 
    static func ==<T2>(lhs: Box<T2>, rhs: Box<T2>) -> Bool { 
     return lhs.id == rhs.id 
    } 

    static func ==<T3: Equatable>(lhs: Box<T3>, rhs: Box<T3>) -> Bool { 
     return lhs.id == rhs.id && lhs.value == rhs.value 
    } 
} 

你的定义改成这样:

extension Box : Equatable { 
    static func ==(lhs: Box<T>, rhs: Box<T>) -> Bool { 
     return lhs.id == rhs.id 
    } 
} 

extension Box where T: Equatable { 
    static func ==(lhs: Box<T>, rhs: Box<T>) -> Bool { 
     return lhs.id == rhs.id && lhs.value == rhs.value 
    } 
} 

而且它按预期工作。

+0

谢谢。清楚并且指向。 –