2015-07-21 81 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