在swift中以泛型类作为参数声明泛型类

时间:2019-07-19 18:24:57

标签: swift

我编写了这些简单的泛型类,并且效果很好:

class LinkedListNode <T> {
    var value: T
    var next: LinkedListNode<T>?
    weak var prev: LinkedListNode<T>?
    init(value: T) {
        self.value = value
        self.next = nil
    }
}

class LinkedList<T> {
    var first: LinkedListNode<T>? = nil
    var last: LinkedListNode<T>? = nil
    var count = 0
    @discardableResult func append(_ value: T) -> LinkedListNode<T> {
        let new = LinkedListNode(value: value)
        new.prev = last
        last?.next = new
        count += 1
        last = new
        if first == nil {
            first = new
        }
        return new
    }
}

我像这样使用它:

let list = LinkedList<Int>()
list.append(3)
let lastNode = list.append(5)

现在,我意识到在某些情况下需要拥有自定义节点:CustomNode<T>LinkedListNode<T>的子类。因此,我希望能够将类用作节点:

let list = LinkedList<CustomNode<Int>>()
list.append(3)
let customNode = list.append(5)

如何声明我的班级有这样或类似的内容?

我尝试了以下声明,但出现了奇怪的错误。这有可能吗?

class LinkedList<Node<T>: LinkedListNode<T>> { ... 

2 个答案:

答案 0 :(得分:1)

您将需要用protocol定义一个associated type

protocol Node: class {
    associatedtype Value
    var value: Value {get set}
    var next: Self? {get set}
    var prev: Self? {get set}

    init(value: Value)
}

final class BasicNode<Value>: Node {
    var value: Value
    var next: BasicNode<Value>?
    weak var prev: BasicNode<Value>?

    init(value: Value) {
        self.value = value
    }
}

final class CustomNode<Value>: Node {
    // customize however you want
    var value: Value
    var next: BasicNode<Value>?
    weak var prev: BasicNode<Value>?

    init(value: Value) {
        self.value = value
    }
}

class LinkedList<N: Node> {
    var first: N? = nil
    var last: N? = nil
    var count = 0

    @discardableResult
    func append(_ value: N.Value) -> N {
        let new = N(value: value)
        new.prev = last
        last?.next = new
        count += 1
        last = new
        if first == nil {
            first = new
        }
        return new
    }
}

但是,这将需要一直烦人地使用基本链接列表:

let list = LinkedList<BasicNode<Int>>()

根据您需要如何自定义节点,我会考虑使用dependency injection在LinkList类本身中找到一种自定义行为的方法。

答案 1 :(得分:0)

您尝试的语法可以通过以下方式实现,

l = ['3.4', '3.2', '2.3', '4.3', '2.3']

for i in range(len(l)):
    if i == list(range(len(l)))[-1]:
        print("└───", end="")
    else:
        print("├───", end="")
    print(l[i])

用法:

class LinkedListNode <T> {
    var value: T
    var next: LinkedListNode<T>?
    weak var prev: LinkedListNode<T>?
    required init(value: T) {
        self.value = value
        self.next = nil
    }
}

class GenericCustomNode<T>: LinkedListNode<T> {

    required init(value: T) {
        super.init(value: value)
    }
}

class NonGenericCustomNode: LinkedListNode<Int> {

    required init(value: Int) {
        super.init(value: value)
    }
}

class LinkedList<T, U: LinkedListNode<T>> {
    var first: U? = nil
    var last: U? = nil
    var count = 0
    @discardableResult func append(_ value: T) -> U {
        let new = U(value: value)
        new.prev = last
        last?.next = new
        count += 1
        last = new
        if first == nil {
            first = new
        }
        return new
    }
}

输出:

let list = LinkedList<Int, LinkedListNode<Int>>()
list.append(5)
print(list.first?.value)

let someCustom = LinkedList<Int, GenericCustomNode<Int>>()
someCustom.append(15)

print(someCustom.first?.value)

let otherCustom = LinkedList<Int, NonGenericCustomNode>()
otherCustom.append(2)
print(otherCustom.first?.value)