简体   繁体   English

迅速-比较符合协议的结构

[英]swift - Comparing structs that conform to a protocol

I have the following structs that represent a point or a line: 我有以下表示点或线的结构:

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
    }

And

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
    }

I want to be able to have a Shape protocol or struct that I can use to have Points and Lines and then I can compare between them. 我希望能够有一个Shape协议或结构,可以用来包含Points and Lines,然后可以在它们之间进行比较。 I tried to that with conforming protocol Shape but Swift compiler gives me an error when I want to compare a point with a line even though they are Shapes. 我尝试使用一致的协议Shape来实现这一点,但是当我想将点与直线进行比较时,即使它们是Shapes,Swift编译器也会给我一个错误。

Do I have to move from struct to classes? 我必须从结构转到类吗?
I think I may have to use generics but don't know exactly how to solve this issue. 我想我可能必须使用泛型,但不确切地知道如何解决此问题。 Thanks in advance for any guidance. 在此先感谢您的指导。

Edit1: 编辑1:

My approach to Shape protocol was really just trying stuff but nothing worked. 我使用Shape协议的方法实际上只是尝试尝试,但没有任何效果。 I tried the following: 我尝试了以下方法:

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

I also changed the code for the Equatable extension for lines given the suggestion 根据建议,我还更改了Equatable扩展的代码

This topic is covered in the WWDC 2015 session video Protocol-Oriented Programming in Swift , and here is my attempt to apply that to your situation: 该主题在WWDC 2015会话视频Swift中的面向协议的编程中有所介绍,这是我尝试将其应用于您的情况:

You define a protocol Shape and a protocol extension method isEqualTo: : 您定义一个协议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: checks if the other element is of the same type (and compares them with == in that case), and returns false if they are of different type. isEqualTo:检查其他元素是否具有相同的类型(在这种情况下,将它们与==进行比较),如果它们具有不同的类型,则返回false

All types which are Equatable automatically conform to Shape , so that we can just set 所有Equatable类型Equatable自动符合Shape ,因此我们可以设置

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

(Of course you can add other methods to Shape which should be implemented by all shape types.) (当然,您可以向Shape添加其他方法,该方法应由所有Shape类型实现。)

Now we can define == for shapes as 现在我们可以为形状定义==

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

and voilà, points and lines can be compared: 和点,可以比较点和线:

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

Remark: You have == for the Shape type now, but I haven't figured out yet to how make Shape conform to Equatable . 备注:现在Shape类型为== ,但是我还不知道如何使Shape符合Equatable Perhaps someone else can solve that part (if it is possible). 也许其他人可以解决这一部分(如果可能)。

Please allow me to shorten and correct your code a bit: 请允许我稍微缩短并更正您的代码:

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
}

I think I know now what you want: 我想我现在知道您想要什么:

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
}

Note: You have to implement == for every shape on its own, because every shape type has different properties 注意:您必须为每个形状==实现== ,因为每种形状类型都有不同的属性

If you want every Shape to have a certain method, you can just add the requirement to the protocol: 如果您希望每个Shape都有特定的方法,则可以将要求添加到协议中:

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

and make every Shape conform to it: 并使每个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)
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM