Я реализую модель дерева. Каждый тип узла может иметь широкий выбор возможностей. Я реализую это с помощью базы class Node {}
, а затем многих протоколов с реализациями по умолчанию для описания возможностей. Затем у меня есть последние классы, производные от Node и соответствующие некоторому списку протоколов, для описания моей структуры.
Каждый протокол имеет связанный код в следующем стиле:
protocol Protocol {}
typealias ProtocolConformingNode = Node & Protocol
extension Node
{
public var isProtocolConforming: Bool {
return asProtocolConforming != nil
}
public var asProtocolConforming: ProtocolConformingNode? {
return self as? ProtocolConformingNode
}
}
Я использую Node & Protocol
, чтобы я мог использовать другие связанные с протоколом запросы для возвращаемых элементов, например, asOtherProtocolConforming
.
Это все работает нормально, пока я не буду иметь дело с массивами ProtocolConformingNode
. Сначала я столкнулся с проблемами фильтрации массивов узлов + протокола, где я хотел сохранить соответствие после фильтрации:
extension Array where Element: Node
{
var someFilter: [Element] {
return self
}
}
let array = [ProtocolConformingNode]()
let filteredArray = array.someFilter
Это дает следующую ошибку:
[ProtocolConformingNode]' (aka 'Array<Node & Protocol>') requires that 'ProtocolConformingNode' conform to 'AnyObject'
Это было немного странно, но я думаю, что подпадает под вопрос, который обсуждался ранее на SO: Протокол не соответствует самому себе?
Я решил, что стирание типов всех моих протоколов будет слишком большим для редких случаев, когда я использовал это, поэтому я был бы доволен приведением своих узлов после фильтрации. Обратите внимание, что я не использую Element
в следующем коде, но явно использую Node
и Element == Node
:
extension Array where Element == Node
{
var someFilter: [Node] {
return self
}
}
let array = [ProtocolConformingNode]()
let filteredArray = array.someFilter as! [ProtocolConformingNode]
Это теперь дает ошибку:
'[ProtocolConformingNode]' (aka 'Array<Node & Protocol>') is not convertible to 'Array<Node>'
Что странно для меня. Я могу заставить это работать так:
let filteredArray = (array as [Node]).someFilter as! [ProtocolConformingNode]
Но почему я должен читать здесь? Как это работает ниже?
var nodes = [Node]()
var protocolConformingNodes = [ProtocolConformingNode]()
nodes.append(contentsOf: protocolConformingNodes)
Когда:
mutating func append<S>(contentsOf newElements: S) where Element == S.Element, S : Sequence