【发布时间】:2016-06-14 15:44:09
【问题描述】:
所以,在使用 SpriteKit 时,我正在尝试使 CGPoint、CGVector 和 CGSize 能够很好地为我工作。所有这些都只是具有垂直和水平分量(向量)的结构。于是我做了一个协议:VectorType
protocol VectorType {
init(x: CGFloat, y: CGFloat)
var x: CGFloat { get set }
var y: CGFloat { get set }
}
当然,我扩展了 3 个结构以符合协议并将x 和y 连接到每个结构的水平和垂直组件,即x 返回dx 为CGVector(设置相同),x 为 CGSize 返回 width ,而 CGPoint 没有任何内容,因为它们符合开箱即用的要求,只是将扩展名留空。
现在我重载了“主要”运算符 (+ - * /...),因此我可以毫不费力地执行涉及不同类型结构的操作,而不必强制转换它们或创建新对象,但这里主要的是我也重载了等价运算符如下:
//Compiler requires me to use generics for some reason
func == <T: VectorType, U: VectorType> (lhs: T, rhs: U) -> Bool {
return (lhs.x == rhs.x) && (lhs.y == rhs.y)
}
func != <T: VectorType, U: VectorType> (lhs: T, rhs: U) -> Bool {
return !(lhs == rhs)
}
现在,当我测试这段代码时,除了!= 运算符外,一切都很好。为了测试这些运算符,我比较了每种类型的大小、大小、向量、大小和点等。当我使用== 时没有问题。
但是,当我使用!= 时,出现了问题。有一个Ambiguous use of operator '!='这样的:
我完全知道这是从哪里来的:== 和 != 运算符比较 CGVector to CGVector、CGPoint to CGPoint 和 CGSize to CGSize 的重载已经存在。它们是这样声明的
@warn_unused_result func ==(lhs: CGSize, rhs: CGSize) -> Bool
每种类型的课程都有重载。所以我得到了歧义的来源,它不知道在比较相同的类型时使用哪个运算符。但是我不明白如果我们的情况基本相同,为什么== 中的== 运算符没有这样的问题。
对我来说这似乎是一个编译器错误,但我不确定,我尝试清理项目、重新启动 Xcode 并创建一个新项目,但仍然无法正常工作。此外,当我尝试查看导致歧义选择 Found this candidate 的其他声明时,它什么也没有显示。
所以,问题是:我怎样才能让它工作,或者你能建议另一种让它工作的方法(不涉及创建不同的运算符)?
更新
我发现实际上正在使用的== 和!= 实现实际上声明不同。这就是声明使用的== 重载的方式
@warn_unused_result func ==(lhs: CGSize, rhs: CGSize) -> Bool
AFAIK 这也应该与我的声明相冲突,但显然没有。
这是另一个!= 重载声明。
@warn_unused_result func !=<T : Equatable>(lhs: T, rhs: T) -> Bool
由于 lhs 和 rhs 具有相同的类型,并且符合 VectorType 协议的所有三种类型都符合 Equatable,因此该重载是该操作的候选对象。
我猜== 会被使用,因为它明确要求CGVector、CGPoint 或CGSize,并且可能优先于泛型。不确定如果您知道为什么两个 == 运算符不冲突,请告诉我。
【问题讨论】:
-
如果您不覆盖
!=定义会发生什么?它有一个基于not ==的默认实现 -
顺便说一句,不要为您自己的类型使用
CG前缀。它通常为 CoreGraphics 保留 -
好吧,我想我可以这样做,但感觉不对,我需要手动比较这是我想要避免的,但如果找不到另一个解决方案是我要走的路。是的,我在考虑 CG 的东西,我会改变它,这只是我命名它时想到的第一件事。
-
“我需要手动比较”嗯?
-
现在我明白了,你的意思是像使用
!(aVector == anotherVector),我想应该不会那么糟糕
标签: swift operator-overloading core-graphics ambiguous