swift - 比较符合协议的结构
swift - Comparing structs that conform to a protocol
我有以下表示点或线的结构:
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 当我想将一个点与一条线进行比较时,即使它们是形状,编译器也会给我一个错误。
我必须从 struct 移动到 类 吗?
我想我可能不得不使用泛型,但不知道如何解决这个问题。
在此先感谢您的指导。
编辑 1:
我对 Shape 协议的方法实际上只是尝试一些东西,但没有任何效果。我尝试了以下方法:
protocol MapShape : Equatable
{
func == (lhs: MapShape, rhs: MapShape ) -> Bool
}
我还根据建议更改了 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
}
注意:您必须为每个形状单独实施 ==
,因为每个形状类型都有不同的属性
如果你想让每个Shape都有一个特定的方法,你可以在协议中添加需求:
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: [=13=].x + dx, y: [=13=].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)
}
}
WWDC 2015 session 视频 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:
检查其他元素是否属于同一类型(并在这种情况下将它们与 ==
进行比较),如果它们是 returns 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
。也许有人
else 可以解决那部分(如果可能的话)。
我有以下表示点或线的结构:
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 当我想将一个点与一条线进行比较时,即使它们是形状,编译器也会给我一个错误。
我必须从 struct 移动到 类 吗?
我想我可能不得不使用泛型,但不知道如何解决这个问题。
在此先感谢您的指导。
编辑 1:
我对 Shape 协议的方法实际上只是尝试一些东西,但没有任何效果。我尝试了以下方法:
protocol MapShape : Equatable
{
func == (lhs: MapShape, rhs: MapShape ) -> Bool
}
我还根据建议更改了 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
}
注意:您必须为每个形状单独实施 ==
,因为每个形状类型都有不同的属性
如果你想让每个Shape都有一个特定的方法,你可以在协议中添加需求:
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: [=13=].x + dx, y: [=13=].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)
}
}
WWDC 2015 session 视频 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:
检查其他元素是否属于同一类型(并在这种情况下将它们与 ==
进行比较),如果它们是 returns 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
。也许有人
else 可以解决那部分(如果可能的话)。