我试图创建2个协议ArithmeticType和MathematicType,它们将用于泛型运算符函数的where子句
protocol ArithmeticType {
func +(lhs: Self, rhs: Self) -> Self
func -(lhs: Self, rhs: Self) -> Self
func *(lhs: Self, rhs: Self) -> Self
func /(lhs: Self, rhs: Self) -> Self
}
extension Int : ArithmeticType {
}
extension Double : ArithmeticType {
}
extension Float : ArithmeticType {
}
ArithmeticType按预期工作,Int,Float和Double符合它。但是以下失败
import Darwin
protocol MathematicType {
func sin(x: Self) -> Self
}
extension Double : MathematicType {
}
extension Float : MathematicType {
}
在我读到的游乐场的控制台输出上:
Playground execution failed: <EXPR>:35:1: error: type 'Double' does not conform to protocol 'MathematicType'
extension Double : MathematicType {
^
<EXPR>:32:10: note: protocol requires function 'sin' with type 'Double -> Self'
func sin(x: Self) -> Self
^
<EXPR>:39:1: error: type 'Float' does not conform to protocol 'MathematicType'
extension Float : MathematicType {
^
<EXPR>:32:10: note: protocol requires function 'sin' with type 'Float -> Self'
func sin(x: Self) -> Self
^
我希望数学函数的行为与上面的运算符相似。有什么办法吗?
==编辑:
现在我意识到试图简化我的问题是一个坏主意。上下文是这个类(可选值的向量)
class Vector<T> {
var data=[T?]()
init(fromArray: Array<T>) {
for i in fromArray {
data.append(i)
}
}
init() {
}
init(count: Int){
for i in 0..<count {
data.append(nil)
}
}
init(count: Int, repeatedValue: T) {
for i in 0..<count {
data.append(repeatedValue)
}
}
func count() -> Int {
return data.count
}
func append(newElement: T?) {
data.append(newElement)
}
subscript(index: Int) -> T? {
let i = index>0 ? index % count() : -index % count()
return data[i]
}
}
在它之外我为+运算符
定义了一个泛型函数func +<T where T: ArithmeticType>(left: Vector<T>, right: Vector<T>) -> Vector<T> {
let resultCount = max(left.count(),right.count())
var result = Vector<T>()
for i in 0..<resultCount {
if left[i] != nil && right[i] != nil {
result.append(left[i]!+right[i]!)
}
else {
result.append(nil)
}
}
return result
}
按预期工作,但是当我尝试将通用sin函数定义为
时func sin<T where T : FloatingPointType>(x: Vector<T>) -> Vector<T>{
var result = Vector<T>()
for i in 0..<x.count() {
if let o = x[i] {
result.append(sin(o))
}
else {
result.append(nil)
}
}
return result
}
我得到了#34;无法找到接受所提供的参数的罪过重&#34;
然后我尝试用MathemticType试图模仿我已经为+ operator
做的事情(ArithmeticType的灵感来自IntegerAritmeticType源,通过命令点击导入swift,而不是我对我所做的事情的了解)
==更新
如果我只为Double
编写专门的函数func sin(x: Vector<Double>) -> Vector<Double>{
var result = Vector<Double>()
for i in 0..<x.count() {
if let o = x[i] {
result.append(Darwin.sin(o))
}
else {
result.append(nil)
}
}
return result
}
它按预期工作。
所以问题可能会成为&#34;我怎样才能将其概括为Double和Float&#34; ?
答案 0 :(得分:2)
编译器错误是因为您将sin()
声明为MathematicType
协议的方法,然后声明Double
实现了MathematicType
,但实际上并未编写sin()
方法。
extension Double {
func sin(x: Double) -> Double {
return Darwin.sin(x)
}
}
我认为这不是你想要的,不是吗?你希望能够写下这个:
let myAngle = 3.14159
let sineValue = myAngle.sin()
如果是这种情况,您的协议和扩展名应如下所示:
protocol MathematicType {
func sin() -> Self
}
extension Double : MathematicType {
func sin() -> Double {
return Darwin.sin(self)
}
}
答案 1 :(得分:2)
您的MathematicType
协议以及您在Float
和Double
扩展程序中对其的一致声明,请Float
和Double
提供{{1}作为实例方法。也就是说,你说应该能够编写如下代码:
sin
请注意,let zero = 0.0 // inferred type Double
zero.sin(1.5707963268) // returns about 1.0
的调用实际上并不与sin
的值相关,因此这可能不是您想要的行为。
你可能希望zero
成为一个自由函数,所以你可以写:
sin
右?
在这种情况下,您的工作已经完成......标准库定义了两者:
sin(1.5707963268)
如果你真正想要的是func sin(x: Double) -> Double
func sin(x: Float) -> Float
可用作通用参数,意思是“你可以采用正弦的类型”,你需要一个通用的MathematicType
函数。像这样的东西(快速kludgy解决方案,可能更好):
sin
(另请注意,已经存在func sine<T: FloatingPointType>(x: T) -> T {
if let v = x as? Double {
return sin(v) as T
}
if let v = x as? Float {
return sin(v) as T
}
fatalError("unknown FloatingPointType")
}
和Float
符合的协议,因此我在示例中使用了该协议。)
答案 2 :(得分:1)
我认为问题是运算符要求和实例方法要求是不同的,即使它们在语法上看起来相似。运营商始终在全球范围内定义,因此运营商要求是全球运营商的要求。另一方面,实例方法要求是实例方法的要求。无法指定全局功能要求。