2015-07-21 97 views
1

我有以下結構代表的點或線:迅速 - 比較結構符合協議

public struct Point{ 
    let x : Double 
    let y : Double 

    init (x : Double, y : Double) 
    { 
     self.x = x 
     self.y = y 
    } 
} 
extension Point : Equatable{} 
    public func ==(lhs: Point, rhs: Point) -> Bool 
    { 
     return lhs.x == rhs.x && lhs.y == rhs.y 
    } 

而且

public struct Line { 
    let points : [Point] 
    init(points : [Point]) 
    { 
     self.points = points 
    } 
} 

extension Line : Equatable {} 
    public func ==(lhs: Line, rhs: Line) -> Bool 
    { 
     return lhs.points == rhs.points 
    } 

我希望能夠有一個形狀協議或結構,我可以使用有點和線,然後我可以比較它們之間。 我試圖用符合協議形狀,但Swift編譯器給我一個錯誤,當我想比較一個點與一個線,即使他們是形狀。

我必須從結構轉移到班?
我想我可能不得不使用泛型,但不知道如何解決這個問題。 在此先感謝您的任何指導。

EDIT1:

我的方法來塑造協議真的只是想的東西,但沒有奏效。我試過如下:

protocol MapShape : Equatable 
{ 
     func == (lhs: MapShape, rhs: MapShape) -> Bool 
} 

我也改變了代碼給出的建議

+0

如果我沒有記錯,在「雨燕協議的程序設計」的WWDC 2015年視頻介紹這個問題。 (在任何情況下,每個Swift程序員都應該看到!) –

+0

你在shape結構體中做了什麼?請分享 – Kametrixom

+0

共享我試圖使用和編輯我的代碼給你的建議@Kametrixom – Franklin

回答

4

該主題將在2015年WWDC會議視頻Protocol-Oriented Programming in Swift,這裏是我的嘗試應用,爲您的情況:

你定義一個協議Shape和協議擴展方法 isEqualTo:

protocol Shape { 
    func isEqualTo(other: Shape) -> Bool 
} 

extension Shape where Self : Equatable { 
    func isEqualTo(other: Shape) -> Bool { 
    if let o = other as? Self { return self == o } 
    return false 
    } 
} 

isEqualTo:檢查該另一元件是相同類型的(並與==在這種情況下進行比較),並且返回false如果它們 是不同的類型。

所有類型的都Equatable自動符合Shape, 這樣我們就可以只設置

extension Point : Shape { } 
extension Line : Shape { } 

(當然你也可以添加其他的方法來Shape應該由所有形狀類型來 實現。)

現在我們可以爲形狀定義==

func ==(lhs: Shape, rhs: Shape) -> Bool { 
     return lhs.isEqualTo(rhs) 
} 

就萬事大吉了,點和線可以進行比較:

let p1 = Point(x: 1, y: 2) 
let p2 = Point(x: 1, y: 3) 
let l1 = Line(points: [p1, p2]) 
let l2 = Line(points: [p1, p2]) 

print(p1 == p2) // false 
print(p1 == l1) // false 
print(l1 == l2) // true 

注:你有==Shape現在鍵入,但我還沒有想出如何使Shape符合Equatable。也許有人可以解決這個問題(如果可能的話)。

+0

我明白Shape不符合Equatable,但這種解決方案適用於我的案例!謝謝 – Franklin

1

請允許我以縮短和糾正你的代碼位Equatable延長線:

struct Point : Equatable { 
    let x : Double 
    let y : Double 
} 

func ==(lhs: Point, rhs: Point) -> Bool { 
    return lhs.x == rhs.x && lhs.y == rhs.y 
} 

struct Line : Equatable { 
    let a : Point 
    let b : Point 
} 

func ==(lhs: Line, rhs: Line) -> Bool { 
    return lhs.a == rhs.a && lhs.b == rhs.b 
} 

我想我現在知道你想要什麼:

protocol Shape : Equatable { 

} 


struct Polygon : Shape { 
    let points : [Point] 
} 

func ==(lhs: Polygon, rhs: Polygon) -> Bool { 
    return lhs.points == rhs.points 
} 



struct Circle : Shape { 
    let center : Point 
    let radius : Double 
} 

func ==(lhs: Circle, rhs: Circle) -> Bool { 
    return lhs.center == rhs.center && lhs.radius == rhs.radius 
} 

注意:你必須執行==對自己的各種形狀,因爲每個形狀類型具有不同的屬性

如果你想每一個形狀有一定的方法,你可以添加要求的協議:

protocol Shape : Equatable { 
    func move(dx: Double, dy: Double) -> Self 
} 

,並盡一切造型符合它:

struct Polygon : Shape { 
    let points : [Point] 

    func move(dx: Double, dy: Double) -> Polygon { 
     return Polygon(points: points.map { Point(x: $0.x + dx, y: $0.y + dy) }) 
    } 
} 

struct Circle : Shape { 
    let center : Point 
    let radius : Double 

    func move(dx: Double, dy: Double) -> Circle { 
     return Circle(center: Point(x: center.x + dx, y: center.y + dy), radius: radius) 
    } 
} 
+0

這種方法的問題是如何我將來會做什麼,而不是一條線我有另一個形狀不能表示爲一個點陣列。 – Franklin

+0

@Franklin你的意思就像一個圓圈?例如, – Kametrixom

+0

,是的。如果我需要@Kametrixom,我可能希望能夠在未來代表一個圈子 – Franklin