swift - 比较符合协议的结构

时间:2015-07-21 18:41:25

标签: swift struct iequatable

我有以下结构代表一个点或一行:

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
    }

我希望能够拥有一个Shape协议或结构,我可以使用它来获得点和线,然后我可以在它们之间进行比较。 我尝试使用符合协议的Shape,但是当我想要将一个点与一个行进行比较时,Swift编译器会给我一个错误,即使它们是Shapes。

我是否必须从结构转移到类? 我想我可能不得不使用泛型,但不知道如何解决这个问题。 提前感谢任何指导。

EDIT1:

我对Shape协议的处理方法实际上只是尝试了一些东西,但没有任何效果。我尝试了以下方法:

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

我还为给定建议的行更改了Equatable扩展的代码

2 个答案:

答案 0 :(得分:4)

WWDC 2015会话视频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符合{{1} }}。也许有人 否则可以解决那个部分(如果可能的话)。

答案 1 :(得分:1)

请允许我稍微缩短并更正您的代码:

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
}

注意:您必须自己为每个形状实现==,因为每个形状类型都有不同的属性

如果您希望每个Shape都有某种方法,您只需将该要求添加到协议中即可:

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

并使每个Shape符合它:

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)
    }
}