user3840978
user3840978

Reputation: 145

Share generic type with nested class in Kotlin

I'm trying to do a simple Dijkstra pathfinder with genericly typed nodes. For this I have my pathfinder class and a nested data class to help. It look like this

class Dijkstra<T, U: Number >(  val graph: Graph<T, U>,
                                val from: Node<T, U>,
                                val to: Node<T, U>) {

    private var nodesDistances = mutableMapOf<Node<T, U>, DijkstraDistanceHelper<T, U>>()

    init {
        graph.getNodeList().forEach { nodesDistances[it] = DijkstraDistanceHelper<T, U>(it, null, null) }

        val currentNode = from

        while (currentNode != to) {
            currentNode.getNeighborhood()?.forEach {
                if (it.destination != currentNode) {
                    //it.value type is U and properly recognized as such
                    val currentDistance = it.value + (nodesDistances[currentNode]!!.distance ?: 0)

                    if (nodesDistances[it.destination]?.distance == null
                        || nodesDistances[it.destination]!!.distance!! > currentDistance) {
                        //compilator error on the compare too, same reason I assume
                        nodesDistances[it.destination]!!.distance = currentDistance
                        nodesDistances[it.destination]!!.parentNode = currentNode
                    }
                }
            }
        }
    }

    private data class DijkstraDistanceHelper<T, U: Number>(  val node: Node<T, U>,
                                                              var distance: U?,
                                                              var parentNode: Node<T, U>?)
}

This is not sound algorithmically speaking but what bother me is that it doesn't compile : the compilator can't comprehend that Dijkstra's U generic type is the same as DijkstraDistanceHelper

Is it the wrong way? How can I enforce that Dijkstra's generic types (both T and U) are the same as DijkstraDistanceHelper?

Upvotes: 0

Views: 829

Answers (1)

Kiskae
Kiskae

Reputation: 25573

There is no way to add abstract Number instances. If you look at the documentation you will see that no plus operator has been defined. This is because adding numbers has different behaviour depending on whether they are floating point and their internal size.

You will need to provide the method to add the U instances, something like (U,U) -> U as a parameter which can be provided during creation as Int::plus or its equivalent.

Upvotes: 1

Related Questions