Редактировать: я переформулировал и, надеюсь, прояснил этот вопрос по здесь . Теперь я добавил решение.
Я определил функцию (см. foo()
в прикрепленном примере) в качестве функции по умолчанию для struct
s, приняв мой protocol
. Он применяет оператор +
, определенный для двух других переменных, которые сами принимают другие protocols
, а +
определен в одном из этих протоколов. Переменные набираются с использованием associatedtype
s. Я получаю сообщение:
Двоичный оператор «+» не может быть применен к операндам типа «Self.PointType» и «Self.VectorType»
Если я реализуюФункция внутри моего struct
(см. bar () в приложении) работает, поэтому я уверен, что мой оператор + работает. Мой пример сведен к минимуму, необходимому для работы на детской площадке. Просто удалите комментарии в LineProtocol extension
, чтобы получить ошибку. Мне кажется, что Self.PointType
- это Point
, а 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)
}
}