在通用 类 中使用通用协议
Using generic protocols in generic classes
我定义了一个协议LLNodeType
:
protocol LLNodeType {
typealias T
var firstNode: LLNode<T>? { get }
}
LLNode<T>
只是一个简单的泛型 class,它包含一个 N
.
类型的存储 属性
class LLNode<N> {
var content: N
...
}
为了符合 LLNodeType
协议,我扩展了 LLNode
如下:
extension LLNode: LLNodeType {
typealias T = N
var firstNode: LLNode<T>? {
return self
}
}
我还定义了一个泛型 class LLLinkedList
,其中包含一些使用泛型类型的属性和函数 L
:
class LLLinkedList<L> {
var rootNode: LLNode<L>?
...
}
我扩展了这个 class 以符合 LLNodeType
:
extension LLLinkedList: LLNodeType {
typealias T = L
var firstNode: LLNode<T>? {
return self.rootNode
}
}
我找到了一种将 LLNodeType
作为常规类型传递给 LLLinkedList
方法的方法,并将其用于 append
方法:
func append<NT: LLNodeType>(nodeSequence: NT) {
let nodes = LLLinkedList(nodeSequence: nodeSequence)
...
}
正如在 append
方法的第一条语句中所见,我还为 LLLinkedList
定义了一个初始化程序,它接受类型为 LLNodeType
的参数 nodeSequence
:
convenience init<NT: LLNodeType where NT.T == L>(nodeSequence: NT) {
self.init()
self.rootNode = nodeSequence.firstNode
}
初始化程序仅采用符合 LLNodeType
的 nodeSequence
,尽管使用等于 L
.
的类型 T
受到限制
一个nodeSequence
的firstNode
一个属性符合这些条件所以应该return一个LLNode<L>?
.
因此语句 self.rootNode = nodeSequence.firstNode
应该是完全可能的,因为 self.rootNode
是类型 LLNode<L>?
.
当我尝试编译代码时,出现错误:
<stdin>:501:33: error: extra argument 'nodeSequence' in call
let nodes = LLLinkedList(nodeSequence: nodeSequence)
501:33
指的是append
方法的第一条语句。
如果我用名为 nodeSequence
的参数定义初始值设定项,怎么会有 extra argument 'nodeSequence'
?
这是一个代码示例,仅包含与问题相关的部分:
SwiftStub-Code
问题是您的 append
函数没有为您追加的序列指定 LLNodeType.T
的类型:
func append<NT: LLNodeType>(nodeSequence: NT) {
// here, nodeSequence could be of a String, an Int, who knows...
let nodes = LLLinkedList(nodeSequence: nodeSequence)
...
// but here you try to append it to the existing list...
// what if it's not a list of the same type?
if self.isEmpty {
self.rootNode = nodes.rootNode
} else {
/// appends a node by pointing the last nodes pointer ('nextNode' property) to the new node
self.lastNode!.nextNode = nodes.rootNode
}
}
您可以通过强制您仅附加与您的
相同类型的序列来解决此问题
func append<NT: LLNodeType where NT.T == L>(nodeSequence: NT) {
// etc...
我定义了一个协议LLNodeType
:
protocol LLNodeType {
typealias T
var firstNode: LLNode<T>? { get }
}
LLNode<T>
只是一个简单的泛型 class,它包含一个 N
.
class LLNode<N> {
var content: N
...
}
为了符合 LLNodeType
协议,我扩展了 LLNode
如下:
extension LLNode: LLNodeType {
typealias T = N
var firstNode: LLNode<T>? {
return self
}
}
我还定义了一个泛型 class LLLinkedList
,其中包含一些使用泛型类型的属性和函数 L
:
class LLLinkedList<L> {
var rootNode: LLNode<L>?
...
}
我扩展了这个 class 以符合 LLNodeType
:
extension LLLinkedList: LLNodeType {
typealias T = L
var firstNode: LLNode<T>? {
return self.rootNode
}
}
我找到了一种将 LLNodeType
作为常规类型传递给 LLLinkedList
方法的方法,并将其用于 append
方法:
func append<NT: LLNodeType>(nodeSequence: NT) {
let nodes = LLLinkedList(nodeSequence: nodeSequence)
...
}
正如在 append
方法的第一条语句中所见,我还为 LLLinkedList
定义了一个初始化程序,它接受类型为 LLNodeType
的参数 nodeSequence
:
convenience init<NT: LLNodeType where NT.T == L>(nodeSequence: NT) {
self.init()
self.rootNode = nodeSequence.firstNode
}
初始化程序仅采用符合 LLNodeType
的 nodeSequence
,尽管使用等于 L
.
T
受到限制
一个nodeSequence
的firstNode
一个属性符合这些条件所以应该return一个LLNode<L>?
.
因此语句 self.rootNode = nodeSequence.firstNode
应该是完全可能的,因为 self.rootNode
是类型 LLNode<L>?
.
当我尝试编译代码时,出现错误:
<stdin>:501:33: error: extra argument 'nodeSequence' in call
let nodes = LLLinkedList(nodeSequence: nodeSequence)
501:33
指的是append
方法的第一条语句。
如果我用名为 nodeSequence
的参数定义初始值设定项,怎么会有 extra argument 'nodeSequence'
?
这是一个代码示例,仅包含与问题相关的部分: SwiftStub-Code
问题是您的 append
函数没有为您追加的序列指定 LLNodeType.T
的类型:
func append<NT: LLNodeType>(nodeSequence: NT) {
// here, nodeSequence could be of a String, an Int, who knows...
let nodes = LLLinkedList(nodeSequence: nodeSequence)
...
// but here you try to append it to the existing list...
// what if it's not a list of the same type?
if self.isEmpty {
self.rootNode = nodes.rootNode
} else {
/// appends a node by pointing the last nodes pointer ('nextNode' property) to the new node
self.lastNode!.nextNode = nodes.rootNode
}
}
您可以通过强制您仅附加与您的
相同类型的序列来解决此问题func append<NT: LLNodeType where NT.T == L>(nodeSequence: NT) {
// etc...