【发布时间】:2019-11-05 13:46:25
【问题描述】:
编辑:我已经重申并希望通过here 澄清这个问题。现在我已经添加了解决方案。
我已经定义了一个函数(参见附件示例中的foo())作为structs 采用我的protocol 的默认函数。它应用了针对其他两个变量定义的 + 运算符,这些变量本身采用其他 protocols 和 + 在其中一个协议中定义。变量使用associatedtypes 输入。
我收到消息:
二元运算符“+”不能应用于“Self.PointType”和“Self.VectorType”类型的操作数
如果我在 struct 中实现该函数(参见附件中的 bar()),它可以工作,所以我确信我的 + 运算符可以工作。
我的例子被缩减到在操场上工作所需的最低限度。只需删除 LineProtocol extension 中的 cmets 即可获得错误。在我看来,Self.PointType 是 Point 而Self.VectorType 是 Vector。
明确一点:我使用associatedtypes 的原因是因为许多不同的structs 采用了示例中的三个协议中的每一个,所以我无法直接命名它们
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)
}
}
【问题讨论】:
-
附带说明:您的类型命名非常混乱。
PointProtocol、PointType、Point。如果您查看 Apple 的 API 设计,他们会尝试限制相似的名称。如果他们没有明确的目的,那么也许你做错了什么 -
对不起,这不是为了混淆。我正在构建的框架适用于几何,适用于点、向量、矩阵、线、平面等。在每种情况下,都有许多子类型,但 struct 不支持继承,所以我使用协议。例如,Point 系列有一个协议(PointProtocol)和几个结构(Point2D、Point3D、Point4D 等),要知道我指的是哪个,我提供了一个
associatedtypePointType。相同的结构用于其他几何对象族。这就是理解命名的全部内容。
标签: swift swift-protocols associated-types default-implementation