简体   繁体   中英

How to use a self-referencing Swift protocol as a type for a generic class

I'm stuck trying to create a linked list of generic nodes using a protocol. I realize there are fifty thousand linked list implementations out there. This is for educational purposes. I've looked over SO for related questions, and read all about protocols and such on swift.org. I've read a few articles about advanced usage on other sites, but I still haven't found something that addresses the problem I'm having.

It seems like a trivial issue; maybe I'm just not asking the right questions? Here's the stripped-down code:

protocol LinkableNode: class {
    func getNextNode() -> LinkableNode?
}

class LinkedList<T: LinkableNode> {
    var head: T?

    func detach() {
        head = head!.getNextNode()  // The call to getNextNode() is the problem
    }
}

I get cannot assign value of type 'LinkableNode?' to type 'T?' cannot assign value of type 'LinkableNode?' to type 'T?' on the call to getNextNode() . I want head to be a node too, and I thought T: LinkableNode would do that, but obviously not. I've tried every permutation under the sun based on the few remotely similar examples I've found, but I'm stuck.

func getNextNode() -> LinkableNode?

defines a method returning a value of some type conforming to LinkableNode , but that need not be the same type as the method is called on.

What you want is

protocol LinkableNode: class {
    func getNextNode() -> Self?
}

This defines a method returning an (optional) value of the same type as it is called on, and makes your remaining code compile.

Side note: Unless you want your code to crash on an empty list, use optional chaining instead of forced unwrapping:

class LinkedList<T: LinkableNode> {
    var head: T?

    func detach() {
        head = head?.getNextNode()
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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