2016-11-21 143 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

謝謝。清楚並且指向。 –