无法转换'NodeType.NodeType?'类型的返回表达式返回类型'NodeType?'

时间:2018-02-20 11:12:09

标签: swift abstract-class swift-protocols

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

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()  
    }
}

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

2 个答案:

答案 0 :(得分:0)

我不确定我是否正确地理解了你的问题(你实际上是在问一对夫妻),但这就是我的模仿方式&#39; Swift(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 的每个Node后代必须实现getNext(),否则我们会崩溃。在操场上运行上面的代码,你会发现它会在最后一行崩溃,迫使你实现getNext()。

&#39;修复&#39;将是:

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的类,实现此NodeOperatable而不实现getNext(),这将强制后代类实现getNext()

答案 1 :(得分:0)

试试这个:

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

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

你称之为什么并不重要。在上面我把它命名为T。在你的作品中,你将其命名为NodeType,如下所示:

class AbstractGraph<NodeType: NodeProtocol>

但重复使用NodeType作为类型名称只会让associatedtype NodeType中的NodeProtocol名称混淆,人们会期望两者都相同,但事实并非如此。

基本上,您的AbstractGraph需要符合T的类型,例如NodeProtocol
由于此类型T符合NodeProtocol,因此其中会自动包含NodeType属性。
此外,根据协议要求,getNode()将返回此NodeType属性 因此,在getRoot(),因为您基本上返回getNode()返回的内容,您需要返回T类型的NodeType属性,而不是类型T本身。