你只需要一个通用的添加:
func +<A: Angle>(lhs: A, rhs: Angle) -> A {
return A(rawRadians: lhs.rawRadians + rhs.rawRadians)
}
这样,添加将返回 lhs 上的任何类型。
一般来说,如果你正在使用dynamicType
,你可能正在与 Swift 作斗争。Swift 更多地依赖泛型和协议(即编译时的静态类型信息)而不是动态调度(即运行时的动态类型信息)。
正如您所说,在此代码中,A
是“某种类型,符合Angle
,在编译时确定”的占位符。所以在你的第一个例子中:
Degrees(180) + Rotations(0.25) --> Degrees(270)
这实际上调用了一个专门的函数+<Degrees>
。和这个:
Rotations(0.25) + Radians(M_PI) -> Rotations(0.75)
调用一个(逻辑上)不同的函数,称为+<Rotations>
. 编译器可以选择将这些函数优化为单个函数,但从逻辑上讲,它们是独立的函数,在编译时创建。它基本上是书写addDegrees(Degrees, Angle)
和addRotations(Rotations, Angle)
手写的捷径。
现在,关于一个需要两个角度并返回的函数的问题......好吧,什么?如果你想Angle
在这种情况下返回一个,这很容易,并且与你的原始签名完全匹配:
func +(lhs: Angle, rhs: Angle) -> Angle {
return Radians(rawRadians: lhs.rawRadians + rhs.rawRadians)
}
“但是……”你是说,“那又回来了Radians
。” 不,它没有。它返回Angle
。你可以在它上面做任何你想做的“角度”。实现细节应该是不透明的。如果您关心底层数据结构是 a Radians
,那么您几乎可以肯定做错了什么。
好的,在一种情况下,了解这一点可能很有用,那就是如果您根据您的操作方式打印出来。因此,如果用户在开始时向您提供了学位信息,那么您希望以学位为单位打印所有内容(使用description
您未提及的方法)。在那种特殊情况下,也许这值得做。如果你愿意,你的原始代码非常接近:
func +(lhs: Angle, rhs: Angle) -> Angle {
return lhs.dynamicType.init(rawRadians: lhs.rawRadians + rhs.rawRadians)
}
但重要的是要理解这与您要求“使用 lhs 参数来指定返回类型”的请求不符。这会导致 lhs 参数指示返回实现。返回类型始终为Angle
。如果要更改返回类型,则需要使用泛型。