我在整个应用中使用了protocols
个vectors
。他们在default implementations
中有一些extensions
,因此我可以为所有types of vectors
实现所有添加的功能。现在,我想用SIMD3
扩展Scalar == Double
,以实现Vector3D协议。 Swift
告诉我,如果我在扩展名中指定Scalar
的类型,那么我还需要为此类型添加Vector3D
的所有依赖项。我不知道为什么选择SIMD3
的关联类型时不会自动发生这种情况,但是可以。所以现在我有了这样的东西:
import UIKit
import simd
protocol DividableByInt {
static func / (lhs: Self, rhs: Int) -> Self
}
protocol HasBasicinitializer {
init()
}
protocol BasicMathOperations {
static func + (lhs: Self, rhs: Self) -> Self
static func - (lhs: Self, rhs: Self) -> Self
static func * (lhs: Self, rhs: Self) -> Self
static func / (lhs: Self, rhs: Self) -> Self
}
protocol Vector: BasicMathOperations, DividableByInt, HasBasicinitializer {
associatedtype Scalar: (SIMDScalar & FloatingPoint)
static var zero: Self { get }
static func calculate(_ lhs: Self, _ rhs: Self, _ operation: (Scalar, Scalar) -> Scalar) -> Self
static func calculate(_ lhs: Self, _ rhs: Scalar, _ operation: (Scalar, Scalar) -> Scalar) -> Self
func allAxesValues() -> [Scalar]
}
extension Vector {
static func + (lhs: Self, rhs: Self) -> Self { return calculate(lhs, rhs, +) }
static func - (lhs: Self, rhs: Self) -> Self { return calculate(lhs, rhs, -) }
static func * (lhs: Self, rhs: Self) -> Self { return calculate(lhs, rhs, *) }
static func / (lhs: Self, rhs: Self) -> Self { return calculate(lhs, rhs, /) }
static func * (lhs: Self, rhs: Scalar) -> Self { return calculate(lhs, rhs, *) }
static func / (lhs: Self, rhs: Scalar) -> Self { return calculate(lhs, rhs, /) }
static func / (lhs: Self, rhs: Int) -> Self { return calculate(lhs, Scalar(rhs), /) }
}
protocol Vector3D: Vector {
init(x: Scalar, y: Scalar, z: Scalar)
var x: Scalar { get }
var y: Scalar { get }
var z: Scalar { get }
}
extension Vector3D {
func allAxesValues() -> [Scalar] {
return [x, y, z]
}
static func calculate(_ lhs: Self, _ rhs: Self, _ operation: (Scalar, Scalar) -> Scalar) -> Self {
return Self(x: operation(lhs.x, rhs.x), y: operation(lhs.y, rhs.y), z: operation(lhs.z, rhs.z))
}
static func calculate(_ lhs: Self, _ rhs: Scalar, _ operation: (Scalar, Scalar) -> Scalar) -> Self {
return Self(x: operation(lhs.x, rhs), y: operation(lhs.y, rhs), z: operation(lhs.z, rhs))
}
}
extension SIMD3: Vector3D where Scalar == Double {}
extension SIMD3: HasBasicinitializer {}
extension SIMD3: DividableByInt where Scalar == Double {}
extension SIMD3: Vector where Scalar == Double {
static let zero = SIMD3(x: 0.0, y: 0.0, z: 0.0)
}
extension SIMD3: BasicMathOperations where Scalar == Double {}
除最后一件事外,所有内容都会自动运行:
extension SIMD3: BasicMathOperations where Scalar == Double {}
编译器说:
Type 'SIMD3<Scalar>' does not conform to protocol 'BasicMathOperations'
但是自从我添加
extension SIMD3: Vector where Scalar == Double
它应该已经实现了所有必需的方法,并且能够继续进行。协议DividableByInt
的继承方式几乎相同,它可以与Vector extension
的实现一起使用。为什么BasicMathOperations
无法使用在Vector extension
中实现的方法?
我知道我可以通过添加
来解决此问题extension SIMD3: BasicMathOperations where Scalar == Double {
static func + (lhs: SIMD3, rhs: SIMD3) -> SIMD3 { return calculate(lhs, rhs, +) }
static func - (lhs: SIMD3, rhs: SIMD3) -> SIMD3 { return calculate(lhs, rhs, -) }
static func * (lhs: SIMD3, rhs: SIMD3) -> SIMD3 { return calculate(lhs, rhs, *) }
static func / (lhs: SIMD3, rhs: SIMD3) -> SIMD3 { return calculate(lhs, rhs, /) }
}
但是我不想重复这段代码,因为它已经在extension Vector
中实现了,应该在那儿使用它。
最后,我只想扩展SIMD3
来实现Vector3D
。如果需要Scalar == Double
或任何可能的标量。
该问题似乎是因为SIMD3已经实现了+,-,/,*之类的功能,并且编译器无法确定要选择哪个功能。我可以从Vector
中删除默认实现,这将解决SIMD3的问题,但随后我需要针对符合Vector的所有其他类型分别实现它。我也将此用于SCNVector3
和CGPoint
。我不知道哪个更好。也许有更好的解决方案,以便我可以对SIMD3以外的所有其他类型实现此功能?
答案 0 :(得分:0)
好的,我想我找到了一个更好的解决方案。我将BasicMathOperations
的默认实现从extension Vector
移到了单独的协议,然后将对新协议的继承添加到了所有与Vector兼容的类型上,除了SIMD3。
// Adds default implementation for BasicMathOperation
protocol VectorWithDefaultImplementationForBasicMathOperations: Vector {}
extension VectorWithDefaultImplementationForBasicMathOperations {
static func + (lhs: Self, rhs: Self) -> Self { return calculate(lhs, rhs, +) }
static func - (lhs: Self, rhs: Self) -> Self { return calculate(lhs, rhs, -) }
static func * (lhs: Self, rhs: Self) -> Self { return calculate(lhs, rhs, *) }
static func / (lhs: Self, rhs: Self) -> Self { return calculate(lhs, rhs, /) }
}
extension CGPoint: VectorWithDefaultImplementationForBasicMathOperations {}
extension SCNVector3: VectorWithDefaultImplementationForBasicMathOperations {}
如果有人知道更好的解决方案,请让我知道,但是我认为这已经很好。