Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用于返回接收器类型(符合协议)的协议的Swift二进制运算符_Swift_Swift2_Binary Operators_Dynamictype - Fatal编程技术网

用于返回接收器类型(符合协议)的协议的Swift二进制运算符

用于返回接收器类型(符合协议)的协议的Swift二进制运算符,swift,swift2,binary-operators,dynamictype,Swift,Swift2,Binary Operators,Dynamictype,为了周五的乐趣,我想以可交换的格式为角度建模。我不确定我是否以最快的惯用方式做到了这一点,但我正在学习。所以我有一个Angle协议,然后是3种不同的结构类型(弧度、度和旋转),它们都符合Angle协议。我希望能够添加/减去它们,但诀窍是,我希望lhs参数指示返回类型。例如: Degrees(180) + Rotations(0.25) --> Degrees(270) 或 我所希望的是我能做些 func + (lhs:Angle, rhs:Angle) -> Angle {

为了周五的乐趣,我想以可交换的格式为角度建模。我不确定我是否以最快的惯用方式做到了这一点,但我正在学习。所以我有一个
Angle
协议,然后是3种不同的结构类型(弧度、度和旋转),它们都符合Angle协议。我希望能够添加/减去它们,但诀窍是,我希望
lhs
参数指示返回类型。例如:

Degrees(180) + Rotations(0.25) --> Degrees(270)

我所希望的是我能做些

func + (lhs:Angle, rhs:Angle) -> Angle {
    return lhs.dynamicType(rawRadians: lhs.rawRadians + rhs.rawRadians)
}
Angle
协议需要
var-rawRadians:CGFloat{get}
以及
init(rawRadians:CGFloat)


我可以用Smalltalk式的双重分派方法来实现这一点,但我认为最合适的方法是更快捷的方法(尤其是需要更少代码的方法,双重分派需要大量样板代码)。

您只需要一个通用的添加:

func +<A: Angle>(lhs: A, rhs: Angle) -> A {
    return A(rawRadians: lhs.rawRadians + rhs.rawRadians)
}
这实际上调用了一个专门的函数
+
。这是:

Rotations(0.25) + Radians(M_PI) -> Rotations(0.75)
调用名为
+
的不同函数(逻辑上)。编译器可以选择将这些函数优化为单个函数,但从逻辑上讲,它们是在编译时创建的独立函数。它基本上是手动写入
addDegrees(度,角度)
addRotations(旋转,角度)
的快捷方式

现在,来回答你关于一个函数的问题,这个函数有两个角度并返回。。。。嗯,什么?在这种情况下,如果要返回
角度
,这很简单,并且与原始签名完全匹配:

func +(lhs: Angle, rhs: Angle) -> Angle {
    return Radians(rawRadians: lhs.rawRadians + rhs.rawRadians)
}
“但是……”你是说,“它会返回
弧度
”不,它不会。它返回
角度
。你可以在上面做任何你想做的事情。实施细节应该是不透明的。如果您关心底层数据结构是
弧度
,那么几乎可以肯定您做错了什么

好的,有一种情况下,了解这一点可能会很有用,那就是如果你是根据你的方式打印出来的。因此,如果用户给了您学位信息开始,那么您希望以学位为单位打印所有内容(使用您没有提到的
description
方法)。在这种特殊情况下,这也许是值得的。如果您愿意,您的原始代码非常接近:

func +(lhs: Angle, rhs: Angle) -> Angle {
    return lhs.dynamicType.init(rawRadians: lhs.rawRadians + rhs.rawRadians)
}

但关键是要理解,这与您的请求不匹配,即“用lhs参数指定返回类型”。这会导致lhs参数指定返回实现。返回类型始终为角度。如果您想更改返回类型,您需要使用泛型。

太棒了!这很有效。如果您有机会的话,如果您能对编译器如何解释语法的泛型部分添加一些解释,我将不胜感激。我模糊地理解了泛型,但还不够。基本上是任何类型的占位符,您可以通过
:Angle
部分约束可接受的贴图?我说得太早了。我刚刚发现了一个问题。如果有两个变量声明为类型
Angle
,没有进一步细化为三个一致结构之一,那么编译器会说
二进制运算符“+”不能应用于两个“Angle”操作数之间
func +(lhs: Angle, rhs: Angle) -> Angle {
    return Radians(rawRadians: lhs.rawRadians + rhs.rawRadians)
}
func +(lhs: Angle, rhs: Angle) -> Angle {
    return lhs.dynamicType.init(rawRadians: lhs.rawRadians + rhs.rawRadians)
}