无法将 'NodeType.NodeType?' 类型的 return 表达式转换为 return 类型 'NodeType?'

Cannot convert return expression of type 'NodeType.NodeType?' to return type 'NodeType?'

我已经在 Swift 中处理这个问题一段时间了,尝试了类型擦除和各种东西,但无济于事;这个问题似乎是常识(至少对我而言)。如何在 Swift 中模拟抽象 class?换句话说,如何进行这项工作:

import Foundation

protocol NodeProtocol
{
    associatedtype NodeType
    func getNode() -> NodeType
}

class Node: NodeProtocol
{
    typealias NodeType = Node
    var next:Node = Node()
    func getNode() -> Node {
        return next
    }
}

class AbstractGraph<NodeType:NodeProtocol>
{
    var root: NodeType?
    func getRoot () -> NodeType?{ 
    return root?.getNode()  
    }
}

注意:这只是我写的一些随机代码,只是为了触及问题的核心。

我不确定我是否正确理解了你的问题(你实际上问了一对夫妇)但这是我 'emulate' 在 [=42= 中抽象 classes 的方式] (4):

protocol Node {
    func getNext() -> Node
}

extension Node {

    func getNext() -> Node {
        fatalError("getNext is not implemented!")
    }

}


struct StringNode: Node {
    var data: String!
}

let sNode = StringNode(data: "test-node-1")

sNode.getNext()

使用协议扩展,我决定需要使用 fatalError() 调用来实现哪些功能。

现在 Node 的每个节点后代都必须 实现 getNext() 否则我们会崩溃。 运行 上面的代码在操场上,你会看到它会在最后一行崩溃,迫使你实现 getNext()。

'fix' 将是:

protocol Node {
    func getNext() -> Node
}

extension Node {

    func getNext() -> Node {
        fatalError("getNext is not implemented!")
    }

}


struct StringNode: Node {
    var data: String!

    func getNext() -> Node {
        return StringNode(data: "test-node-2")
    }
}

let sNode = StringNode(data: "test-node-1")

sNode.getNext()

现在它不会在最后一行崩溃了。全部使用 Xcode 9 和 Swift 4.

在操场上测试

注意:这当然不是 Node 协议的最佳实现。该协议应列出可操作的方法,这些方法应表示 Node 称为 NodeOperatable 之类的东西。应创建名为 Node 的 class 来实现此 NodeOperatable 而不是实现 getNext(),这将迫使后代 classes 实现 getNext()

试试这个:

class AbstractGraph<T: NodeProtocol> {
    var root: T?

    func getRoot () -> T.NodeType? {
        return root?.getNode()
    }
}

你怎么称呼类型并不重要。在上面我把它命名为T。在您的系统中,您已将其命名为 NodeType,如下所示:

class AbstractGraph<NodeType: NodeProtocol>

但是将 NodeType 重用为类型名称只是与 NodeProtocol 中的 associatedtype NodeType 名称有点混淆,人们希望两者相同,但实际上并非如此。

基本上你的 AbstractGraph 需要一个符合 NodeProtocol.
的类型,比如 T 由于此类型 T 符合 NodeProtocol,因此它自动包含 NodeType 属性。
此外,根据协议要求,getNode() 是 return this NodeType 属性.
因此在 getRoot() 中,因为你基本上 returning 什么 getNode() 是 returning,你需要 return 类型 TNodeType 属性,而不是类型 T 本身。