我正在尝试创建两个协议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 {
}
算术类型按预期工作,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
}
这个函数按预期工作,但是当我尝试定义一个通用的正弦函数时
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
}
我得到了“找不到接受所提供参数的正弦重载”的错误提示。
之后,我尝试使用MathematicType来模仿我已经为+运算符完成的操作。
(ArithmeticType是从导入Swift的源代码IntegerAritmeticType中获得启发的,而不是我对自己正在做什么的了解)
== 更新
如果我只为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
}
它按预期工作。
所以问题可能变成“如何将其推广到Double和Float”?
extension Double : MathematicType, ArithmeticType { }
- Atomixfunc sin<T where T : FloatingPointType>
示例看起来不错,但是它不能调用标准库的sin
函数,需要检查和转换其参数类型 -- 请参考我的回答及其新评论。 - ricksterfunc sin<T where T : FloatingPointType>
中检查类型的意义,与其如此,不如有一些专门的func sin(x: Vector<Double>) -> Vector<Double>
和 Float 的相同函数。在这两种情况下,这对于泛型编程来说是一个强大的限制。我想知道自由函数是否被故意从泛型编程中省略,或者苹果认为它们可能没有用处。 - Uli