我定义了一个简单的通用结构 - 它唯一的要求是它的存储属性为Comparable
:
struct Bounds<A: Comparable> {
let lower: A
let upper: A
}
但是,我想为结构提供一些专门的初始化器,它们会使用一些数学运算来设置属性。
init(value: Double, tolerance: Percentage) {
self.lower = value * ( 1 - tolerance )
self.upper = value * ( 1 + tolerance )
}
init(value: Measurement, tolerance: Percentage) {
self.lower = value.value * ( 1 - tolerance )
self.lower = value.value * ( 1 - tolerance )
}
结果显然应该是两种不同的结构,其中A是Double
或Measurement
。
但是我该怎么做?
我无法在定义中提供专门的init方法,因为编译器会抱怨Double is not convertible to A
。 OK ......
我无法在编译器抱怨的情况下,在特定类型(where A == Double
)约束的单个扩展中提供init方法:
相同类型的要求使得通用参数&#39; A&#39;非通用
也许我应该使用Double
和Measurement
在初始化中符合的协议,但这似乎很奇怪,因为Bounds
结构应该只关心它们是否符合{ {1}}。
我觉得我要么缺少一些非常简单的东西,要么试图做一些真正误导仿制药的东西。这是什么,SO?
答案 0 :(得分:1)
不完全是你要求的,但可能的解决方法(Swift 3):
extension Bounds where A: FloatingPoint {
init(value: A, tolerance: A) {
self.lower = value * ( A(1) - tolerance )
self.upper = value * ( A(1) + tolerance )
}
}
let b = Bounds(value: 4.0, tolerance: 0.1)
print(b.dynamicType) // Bounds<Double>
答案 1 :(得分:0)
您可以更强烈地限制通用,以访问协议中的蓝图方法以进行转换,例如通用类型的Double
值。
protocol FromDoubleTransformable {
static func doubleToSelf(from: Double) -> Self
}
/* drawback: only types conforming to 'FromDoubleTransformable'
will be able to be used as generic in 'Bounds' below */
extension Int: FromDoubleTransformable {
static func doubleToSelf(from: Double) -> Int {
// simple example without any out-of-bounds checking
return Int(from)
}
}
struct Bounds<A: protocol<Comparable, FromDoubleTransformable>> {
let lower: A
let upper: A
init(value: Double, tolerance: Double) {
self.lower = A.doubleToSelf(value * ( 1 - tolerance ))
self.upper = A.doubleToSelf(value * ( 1 + tolerance ))
}
}
let foo = Bounds<Int>(value: 120, tolerance: 0.1)
print(foo.dynamicType) // Bounds<Int>
print(foo.lower, foo.upper) // 108 132
答案 2 :(得分:0)
主要问题是您正在对尚未定义操作的类型执行操作。
E.g。
process.removeAllListeners('uncaughtException');
value * ( 1 - tolerance )
和-
之间的操作Int
在哪里定义?
这是你可以解决它的方法
Tolerance
答案 3 :(得分:0)
对此的正确答案是Martin R.的“解决方法”。这里的问题是Comparable
没有定义任何这些数学运算,甚至根本不保证它是数字类型。它可以很容易地成为字符串,数组或实现Comparable
的任何其他类型。
所以,是的,您必须编写受限于实现这些运算符的公共协议或相关具体类型的扩展。例如:
extension Bounds where A: FloatingPoint {
init(value: A, tolerance: Percentage) {
self.lower = value * ( 1 - tolerance )
self.upper = value * ( 1 + tolerance )
}
}
或者,如果Measurement
不符合FloatingPoint
:
extension Bounds where A == Measurement {
init(value: A, tolerance: Percentage) {
self.lower = value.value * ( 1 - tolerance )
self.upper = value.value * ( 1 + tolerance )
}
}
另外,既然你可能不想为你的边界使用任何非数字类型,那么我会把它定义为以下几行:
struct Bounds<A: Numeric & Comparable> {
let upper: A
let lower: A
}