简体   繁体   English

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

[英]declare generic class with a generic class as a parameter in swift

I wrote these simple generic classes and it worked great: 我写了这些简单的通用类,效果很好:

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

And I used it like: 我像这样使用它:

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

Now I realized there are some cases when I need to have a customized node: CustomNode<T> , subclass of LinkedListNode<T> . 现在,我意识到在某些情况下需要一个自定义节点: CustomNode<T>LinkedListNode<T>子类。 So I would like to be able to pass the class to be used as the node as: 因此,我希望能够将类用作节点:

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

How can I declare my class to have it like this or something similar? 如何声明我的班级有这样或类似的内容?

I have tried the following declaration but weird errors rise. 我尝试了以下声明,但出现了奇怪的错误。 Is this even possible? 这有可能吗?

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

Update 2019/07/26. 更新2019/07/26。

Even with Kamran's approach this method does not compile. 即使采用Kamran的方法,该方法也无法编译。 I am not sure if this is doable without a protocol. 我不确定在没有协议的情况下是否可行。 See my comment on Kamran's answer. 请参阅我对Kamran答案的评论。

func remove(node: LinkedListNode<T>) { // change to `func remove(node: U)`
    node.next?.prev = node.prev
    node.prev?.next = node.next
    if node === first {
        first = first?.next
    }
    if node === last {
        last = last?.prev // Error here: "Cannot assign value of LinkedListNode<T>? to U?"
    }
}

You will need to define a protocol with an 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
    }
}

However, this will require using your basic linked list in an annoying way all the time: 但是,这将需要一直烦人地使用基本链接列表:

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

Depending on how you need to customize the node, I would consider finding a way to customize the behavior in the LinkList class itself using dependency injection . 根据您需要自定义节点的方式,我将考虑找到一种使用依赖项注入自定义LinkList类本身中行为的方法。

The syntax you are trying can be achieved as below, 您尝试的语法可以通过以下方式实现,

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
    }

    func remove(node: U) {
        node.next?.prev = node.prev
        node.prev?.next = node.next
        if node === first {
            first = first?.next as? U
        }
        if node === last {
            last = last?.prev as? U
        }
    }
}

Usage: 用法:

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)

Output: 输出:

 Optional(5) 
 Optional(15) 
 Optional(2)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM