假设我有两个符合协议(protocol)的结构,
protocol NumberType {
var doubleValue: Double { get }
}
struct Rational: NumberType {
let numerator: Int
let denominator: Int
var doubleValue: Double { get { return Double(numerator) / Double(denominator) } }
}
struct FixedPoint: NumberType {
let value: Double
var doubleValue: Double { get { return value } }
}
我想为 NumberType
定义算术运算符,它将依次返回 NumberType
。
func *(lhs: NumberType, rhs: NumberType) -> NumberType { return FixedPoint(lhs.doubleValue * rhs.doubleValue) }
但我还想添加更具体的运算符,因此当两者都是 Rational
时,我返回一个 Rational
。
func *(lhs: Rational, rhs: Rational) -> NumberType { return Rational(...) }
有没有比每个运算符都有一个执行所有类型检查的 super 函数更优雅的方法来做到这一点?
编辑
您应该能够将 FixedPoint 乘以 Rational,因为它们都符合 NumberType。
重载策略将不起作用,因为如果我执行 a * b * c
,其中所有值都是 Rational
,a * b< 的结果
是 NumberType
,因此 (a * b) * c
将退回到使用通用 NumberType
乘法运算符。我会在这里失去我的精度。
我不介意能够乘以 Doubles
、Ints
等
进一步编辑
假设最通用的情况总是返回一个 FixedPoint
是不正确的。我在这里展示了基本用法,但是如果你有一个等于 0
的 FixedPoint
和另一个 Rational
,并且你想添加它们,在最通用的情况下,您可以获得 Rational
是可行的。
最佳答案
你可以在这里使用泛型......
如果你像这样定义协议(protocol)......
protocol NumberType {
var doubleValue: Double { get }
init(doubleValue double: Double)
}
然后你可以定义一个函数...
func *<T: NumberType>(lhs: T, rhs: T) -> T {
return T(doubleValue: lhs.doubleValue * rhs.doubleValue)
}
这将允许您将此函数用于任何类型的对象,只要它符合 NumberType
。唯一需要注意的是 lhs
和 rhs
必须是同一类型。
然后在每个 NumberType 的实现中,您可以定义 init 如何工作...
struct FixedPoint: NumberType {
let value: Double
var doubleValue: Double { get { return value } }
init(doubleValue double: Double) {
// this implementation may not be practical for things like Rationals etc...
self.value = double
}
}
如果没有一些创建 NumberTypes
的通用方法,那么您将不得不对该函数的工作方式进行多次实现,因此您需要根据输入内容创建多个实例的方法。
关于协议(protocol)的 Swift 运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42201960/