编辑:我已经重申并希望在这里澄清这个问题。现在我已经添加了解决方案。
我已经定义了一个函数(见foo()
附件示例)作为struct
s 采用 my protocol
. 它应用+
针对其他两个变量定义的运算符,这些变量本身采用其他变量protocols
并+
在其中一个协议中定义。变量使用associatedtype
s 输入。我收到消息:
二元运算符“+”不能应用于“Self.PointType”和“Self.VectorType”类型的操作数
如果我在我的内部实现该函数struct
(参见附件中的 bar())它可以工作,所以我确信我的 + 运算符确实有效。我的例子被缩减到在操场上工作所需的最低限度。只需删除中的注释LineProtocol extension
即可获得错误。在我看来,这Self.PointType
是 aPoint
并且Self.VectorType
是Vector
.
明确一点:我之所以使用associatedtype
s 是因为很多不同struct
的 s 都采用了示例中的三种协议中的每一种,所以我不能直接命名它们
public protocol PointProtocol {
associatedtype VectorType: VectorProtocol
var elements: [Float] { get set }
}
extension PointProtocol {
public static func +(lhs: Self, rhs:VectorType) -> Self {
var translate = lhs
for i in 0..<2 { translate.elements[i] += rhs.elements[i] }
return translate
}
}
public protocol VectorProtocol {
associatedtype VectorType: VectorProtocol
var elements: [Float] { get set }
}
public struct Point: PointProtocol {
public typealias PointType = Point
public typealias VectorType = Vector
public var elements = [Float](repeating: 0.0, count: 2)
public init(_ x: Float,_ y: Float) {
self.elements = [x,y]
}
}
public struct Vector: VectorProtocol {
public typealias VectorType = Vector
public static let dimension: Int = 2
public var elements = [Float](repeating:Float(0.0), count: 2)
public init(_ x: Float,_ y: Float) {
self.elements = [x,y]
}
}
public protocol LineProtocol {
associatedtype PointType: PointProtocol
associatedtype VectorType: VectorProtocol
var anchor: PointType { get set }
var direction: VectorType { get set }
}
extension LineProtocol {
// public func foo() -> PointType {
// return (anchor + direction)
// }
}
public struct Line: LineProtocol {
public typealias PointType = Point
public typealias VectorType = Vector
public var anchor: PointType
public var direction: VectorType
public init(anchor: Point, direction: Vector) {
self.anchor = anchor
self.direction = direction
}
public func bar() -> Point {
return (anchor + direction)
}
}
let line = Line(anchor: Point(3, 4), direction: Vector(5, 1))
print(line.bar())
//print(line.foo())
改编自@Honey 建议的解决方案:将扩展名替换为:
extension LineProtocol where Self.VectorType == Self.PointType.VectorType {
public func foo() -> PointType {
// Constraint passes VectorType thru to the PointProtocol
return (anchor + direction)
}
}