Swift 3中通用协议内的通用协议

时间:2017-04-07 21:39:09

标签: swift generics protocols

我想在Swift中为Tree创建一个接口(协议)。该树将使用TreeNodes的接口(协议)。但所有这些接口都应该是通用的。理想情况下,我想要这样的东西:

protocol TreeNodeInterface {
    associatedtype T: ElementInterface

    var value: T { get set }

    // ... some other methods
 }

protocol TreeInterface {
    var rootNode: TreeNodeInterface<T>? { get }

    func clean()

    // .. some other methods
}

class Tree<T: ElementInterface>: TreeInterface {
    var root: TreeNodeInterface<T>?

    var rootNode: TreeNodeInterface<T>? {
        get {
            return root
        }
    }

    func clean() {

    }
}

因此,例如,我将从TreeInterface继承类Tree,并且我可以使用任何类型(Int,String,CustomClass等)初始化该树,以便每个节点都将该类型作为值。

我设法通过面向对象编程实现了这一目标,但是无法通过面向协议编程实现这一目标

斯威夫特不允许我这样做。有人可以帮我吗? 感谢

1 个答案:

答案 0 :(得分:1)

我认为您正在尝试使用协议做太多事情。这里最大的问题是,如果协议具有关联类型(或自我要求),则无法使用协议类型创建变量。通过用泛型替换这些定义,我最终得到了这个:

protocol TreeNodeInterface {
    associatedtype Element: ElementInterface

    var value: Element { get set }

    // ... some other methods
}

protocol TreeInterface {
    associatedtype Node: TreeNodeInterface

    var rootNode: Node? { get }

    func clean()

    // .. some other methods
}

class Tree<T: TreeNodeInterface>: TreeInterface {
    typealias Node = T
    var rootNode: T?

    init() {}

    func clean() {

    }
}

这个编译,但现在你必须弄清楚如何初始化它。下一步是创建一个符合TreeNodeInterface的类型:

struct TreeNode<T: ElementInterface>: TreeNodeInterface {
    typealias Element = T
    var value: T
}

这看起来非常类似于协议,但这没关系。现在让我们初始化Tree

// Assuming that Int conforms to ElementInterface
let tree = Tree<TreeNode<Int>>()

Phew!这是很多工作,我认为其中大部分是不必要的。你真的需要TreeNodeInterfaceTreeInterface吗?我认为你没有。以下是使用具体类型时的样子:

struct TreeNode<T: ElementInterface> {
    var value: T
}

class Tree<T: ElementInterface> {
    var root: TreeNode<T>?

    init() {}

    func clean() {

    }
}

let tree = Tree<Int>()