所以,在尝试使用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
会为width
返回CGSize
,而CGPoint
则不会为+ - * /
提供任何内容,因为它们开箱即用扩展名为空。
现在我重载了“main”运算符(//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
的{{1}}和CGSize to CGSize
运算符的重载已经存在。它们被声明为
@warn_unused_result func ==(lhs: CGSize, rhs: CGSize) -> Bool
每种类型的课程都有过载。所以我得到了模糊性的来源,它不知道在比较相同的类型时使用哪个运算符。但是我不明白为什么==
中的testEqual()
运算符没有这样的问题,如果我们基本上有相同的情况。
这似乎是一个编译器错误,但我不确定,我尝试清理项目,重新启动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
,并且可能优先于泛型。如果您知道为什么两个==
运营商都不会发生冲突,请不要告诉我。
答案 0 :(得分:2)
如果您的类型符合Equatable
,则需要为其定义等于运算符==
,然后标准库为您提供不等式运算符!=
。运营商。
(事实上,如果您查看Equatable
protocol requirements,唯一需要的功能是func ==
)
您的歧义错误是因为有两个定义:您自己的定义和编译器提供的定义。它们都具有相同的签名,因此编译器无法解析它。
不要自己定义func !=
- 使用提供的。
如果您发现需要定义它,那么您可能并不真正使用Equatable
类型。
<强>更新强>
你没有使用equatable类型。询问一个点是否等于一个大小是没有意义的。你的问题源于试图强迫它具有意义。
您为每种类型的组合提供了一个Equality运算符。因此,您提供CGPoint()==CGVector()
,CGPoint()!=CGVector()
,CGPoint()=CGSize()
和CGPoint()!=CGSize()
,但您还提供了CGPoint()==CGPoint()
和CGPoint()!=CGPoint()
,这与CoreGraphics中的那些。请继续阅读,了解您收到错误消息的原因,以及为什么==
似乎有效。
<强>平等:强>
CGPoint,CGVector和CGSize都符合Equatable
,并提供一个等式运算符,其中双方的类型相同。
然后,您通过扩展程序提供了一个适用于这些类型的相等运算符:
func == <T: VectorType, U: VectorType> (lhs: T, rhs: U) -> Bool
这声明了一个对两个VectorType
对象起作用的相等运算符,即使它们具有不同的基础类型。
编译器首先搜索直接匹配,然后如果找不到它,则尝试通过替换普通类型中的类型来生成一个。
因此,当您说CGPoint()==CGPoint()
时,它会查找它在CoreGraphics中找到的func ==(lhs:CGPoint, rhs:CGPoint)->Bool
。
当您说CGPoint()==CGVector()
时,它会查找func ==(lhs:CGPoint, rhs:CGVector)->Bool
。这在CoreGraphics或其他任何地方都没有定义,所以它继续从通用定义构建一个。
您提供了:
func == <T: VectorType, U: VectorType> (lhs: T, rhs: U) -> Bool
通过您的协议和扩展程序,因此需要您的定义,将T
替换为CGPoint
,将U
替换为CGVector
来生成:
func == (lhs:CGPoint, rhs:CGPoint) -> Bool
它找到了一个(也是唯一一个)可用的定义,因此它使用它。
<强>不等式:强>
当您说CGPoint()!=CGPoint()
时,它会查找未定义的func !=(lhs:CGPoint, rhs:CGPoint)->Bool
。它转而从通用定义构建一个。它找到了
func !=(lhs:T, rhs:T)->Bool
在标准库中,用T
代替CGPoint
来生成:
func!=(lhs:CGPoint,rhs:CGPoint) - &gt; Bool
满足要求。
但是,因为你已宣布:
func != <T: VectorType, U: VectorType> (lhs: T, rhs: U) -> Bool
(直接或通过Equatable
)
它可以用CGPoint替换T
和U
来获取:
func !=(lhs:CGPoint, rhs:CGPoint)->Bool
现在有两种方法可以满足要求。没有办法决定它应该使用哪个定义,所以它会因模糊错误而停止。