Swift 4 个泛型
Swift 4 Generics
我正在尝试学习 Swift 4 个泛型,并且编写了一些无法编译的代码。我不明白为什么。这是代码:
protocol NodeType {
associatedtype T
associatedtype E
var parent: T {get set}
var children: [T] {get set}
var item: E {get set}
func getItem()->E
mutating func setItem(_ newItem: E)
func getParent()->T
mutating func setParent(_ theParent:T)
func getChild(at index:Int)->T
mutating func insertChild(at index:Int, child: T)
func find(_ node:T)->Int
}
protocol ItemType:Equatable {
associatedtype E
var payload: E {get set}
func matches(_ item:E)->Bool
}
struct Item<E:Equatable>: ItemType {
var payload: E
func matches(_ item: E) -> Bool {
return payload == item
}
}
struct Node<T:NodeType, E:ItemType>: NodeType {
var parent: T
var children: [T]
var item: E
func getItem()->E {
return item
}
func find(_ node: T) -> Int {
for aNode in children {
// ********************************************************************
// the following line fails: Value of type 'T.E' has no member 'matches'
if aNode.getItem().matches(node) {
}
}
}
mutating func setItem(_ newItem: E) {
item = newItem
}
func getParent()->T {
return parent
}
mutating func setParent(_ theParent:T) {
parent = theParent
}
func getChild(at index:Int)->T {
precondition(0..<children.count ~= index)
return children[index]
}
mutating func insertChild(at index:Int, child: T) {
precondition(0...children.count ~= index)
if index == children.count {
// append at end
children.insert(child, at: children.endIndex)
}
else {
children.insert(child, at: index)
}
}
}
我的理解是,aNode 的类型 T 约束为 NodeType,而 aNode.getItem() 的类型 E 约束为 ItemType,其中包含函数 matches。谁能告诉我哪里错了。
我认为问题在于您一直使用占位符名称 T
和 E
搞糊涂了。此声明中的E
:
struct Node<T:NodeType, E:ItemType>
... 不是此声明中的 E
:
protocol NodeType {
associatedtype T
associatedtype E
没有理由相信 NodeType 的 E
是 ItemType 采用者,或者它是 Equatable。
如果您在不同的泛型中为占位符选择不同的名称,这对您来说会更加明显(您可以使用 Xcode 的重构功能来帮助您)。例如:
protocol NodeType {
associatedtype NodeTypeParent
associatedtype NodeTypeItem
// ...
}
protocol ItemType:Equatable {
associatedtype ItemTypePayload
// ...
}
struct Item<ItemPayload:Equatable>: ItemType {
// ...
}
struct Node<NodeParent:NodeType, NodeItem:ItemType>: NodeType {
// ...
}
现在您会收到消息
Value of type 'NodeParent.NodeTypeItem' has no member 'matches'
我觉得这样就清楚多了。
看了 Matt 的回答后,我意识到 NodeType 的基本结构是错误的,部分原因是我混淆了通用占位符。下面的代码现在可以编译了。
fileprivate let NotFound = -1
protocol NodeType {
associatedtype Node
associatedtype Element:Equatable
var parent: Node? {get set}
var children: [Node] {get set}
var item: Element {get set}
func isRoot()->Bool
func getItem()->Element
mutating func setItem(_ newItem: Element)
func getParent()->Node?
mutating func setParent(_ theParent:Node)
func getChild(at index:Int)->Node
mutating func insertChild(at index:Int, child: Node)
func matches(_ node:Node)->Bool
func find(_ node:Node)->Int
}
class TreeNode<ThisNodeElement:Equatable>: NodeType {
var parent: TreeNode?
var children: [TreeNode]
var item: ThisNodeElement
init(withNode node:TreeNode, value:ThisNodeElement) {
parent = node
item = value
children = []
}
init(root value:ThisNodeElement) {
parent = nil
item = value
children = []
}
func isRoot() -> Bool {
return parent == nil
}
func getItem()->ThisNodeElement {
return item
}
func setItem(_ newItem: ThisNodeElement) {
item = newItem
}
func getParent()->TreeNode? {
return parent
}
func setParent(_ theParent:TreeNode) {
parent = theParent
}
func getChild(at index:Int)->TreeNode {
precondition(0..<children.count ~= index)
return children[index]
}
func insertChild(at index:Int, child: TreeNode) {
precondition(0...children.count ~= index)
if index == children.count {
// append at end
children.insert(child, at: children.endIndex)
}
else {
children.insert(child, at: index)
}
}
func matches(_ node:TreeNode)->Bool {
return node.item == item
}
func find(_ node: TreeNode) -> Int {
let index = children.index { (thisNode:TreeNode) -> Bool in
return node.matches(thisNode)
}
return index ?? NotFound
}
}
我正在尝试学习 Swift 4 个泛型,并且编写了一些无法编译的代码。我不明白为什么。这是代码:
protocol NodeType {
associatedtype T
associatedtype E
var parent: T {get set}
var children: [T] {get set}
var item: E {get set}
func getItem()->E
mutating func setItem(_ newItem: E)
func getParent()->T
mutating func setParent(_ theParent:T)
func getChild(at index:Int)->T
mutating func insertChild(at index:Int, child: T)
func find(_ node:T)->Int
}
protocol ItemType:Equatable {
associatedtype E
var payload: E {get set}
func matches(_ item:E)->Bool
}
struct Item<E:Equatable>: ItemType {
var payload: E
func matches(_ item: E) -> Bool {
return payload == item
}
}
struct Node<T:NodeType, E:ItemType>: NodeType {
var parent: T
var children: [T]
var item: E
func getItem()->E {
return item
}
func find(_ node: T) -> Int {
for aNode in children {
// ********************************************************************
// the following line fails: Value of type 'T.E' has no member 'matches'
if aNode.getItem().matches(node) {
}
}
}
mutating func setItem(_ newItem: E) {
item = newItem
}
func getParent()->T {
return parent
}
mutating func setParent(_ theParent:T) {
parent = theParent
}
func getChild(at index:Int)->T {
precondition(0..<children.count ~= index)
return children[index]
}
mutating func insertChild(at index:Int, child: T) {
precondition(0...children.count ~= index)
if index == children.count {
// append at end
children.insert(child, at: children.endIndex)
}
else {
children.insert(child, at: index)
}
}
}
我的理解是,aNode 的类型 T 约束为 NodeType,而 aNode.getItem() 的类型 E 约束为 ItemType,其中包含函数 matches。谁能告诉我哪里错了。
我认为问题在于您一直使用占位符名称 T
和 E
搞糊涂了。此声明中的E
:
struct Node<T:NodeType, E:ItemType>
... 不是此声明中的 E
:
protocol NodeType {
associatedtype T
associatedtype E
没有理由相信 NodeType 的 E
是 ItemType 采用者,或者它是 Equatable。
如果您在不同的泛型中为占位符选择不同的名称,这对您来说会更加明显(您可以使用 Xcode 的重构功能来帮助您)。例如:
protocol NodeType {
associatedtype NodeTypeParent
associatedtype NodeTypeItem
// ...
}
protocol ItemType:Equatable {
associatedtype ItemTypePayload
// ...
}
struct Item<ItemPayload:Equatable>: ItemType {
// ...
}
struct Node<NodeParent:NodeType, NodeItem:ItemType>: NodeType {
// ...
}
现在您会收到消息
Value of type 'NodeParent.NodeTypeItem' has no member 'matches'
我觉得这样就清楚多了。
看了 Matt 的回答后,我意识到 NodeType 的基本结构是错误的,部分原因是我混淆了通用占位符。下面的代码现在可以编译了。
fileprivate let NotFound = -1
protocol NodeType {
associatedtype Node
associatedtype Element:Equatable
var parent: Node? {get set}
var children: [Node] {get set}
var item: Element {get set}
func isRoot()->Bool
func getItem()->Element
mutating func setItem(_ newItem: Element)
func getParent()->Node?
mutating func setParent(_ theParent:Node)
func getChild(at index:Int)->Node
mutating func insertChild(at index:Int, child: Node)
func matches(_ node:Node)->Bool
func find(_ node:Node)->Int
}
class TreeNode<ThisNodeElement:Equatable>: NodeType {
var parent: TreeNode?
var children: [TreeNode]
var item: ThisNodeElement
init(withNode node:TreeNode, value:ThisNodeElement) {
parent = node
item = value
children = []
}
init(root value:ThisNodeElement) {
parent = nil
item = value
children = []
}
func isRoot() -> Bool {
return parent == nil
}
func getItem()->ThisNodeElement {
return item
}
func setItem(_ newItem: ThisNodeElement) {
item = newItem
}
func getParent()->TreeNode? {
return parent
}
func setParent(_ theParent:TreeNode) {
parent = theParent
}
func getChild(at index:Int)->TreeNode {
precondition(0..<children.count ~= index)
return children[index]
}
func insertChild(at index:Int, child: TreeNode) {
precondition(0...children.count ~= index)
if index == children.count {
// append at end
children.insert(child, at: children.endIndex)
}
else {
children.insert(child, at: index)
}
}
func matches(_ node:TreeNode)->Bool {
return node.item == item
}
func find(_ node: TreeNode) -> Int {
let index = children.index { (thisNode:TreeNode) -> Bool in
return node.matches(thisNode)
}
return index ?? NotFound
}
}