超类属性未在Derived类中初始化

时间:2017-05-14 21:46:58

标签: inheritance kotlin

我有以下Kotlin代码:

import java.util.*
import kotlin.collections.HashSet

open class Graph(open val n: Int) {
    val graph = List<MutableSet<Int>>(n) {HashSet<Int>()}

    open fun addEdge(u: Int, v: Int) {
        graph[u].add(v)
        graph[v].add(u)
    }

    val numEdges: Int
        get() {
            return graph.asSequence()
                    .map { it.size }
                    .reduce { x, y -> x + y }
        }   

    fun edgeSet() : HashSet<Pair<Int,Int>> {
        val result = HashSet<Pair<Int,Int>>()
        for (i in graph.indices) {
            for(j in graph[i]) {
                if(i<j) result.add(i to j)
                else result.add(j to i)
            }
        }
        return result;
    }

    override fun toString(): String {
        return "Graph(n=$n, graph=$graph)"
    }
}

class DGraph(override val n: Int) : Graph(n) {
    override fun addEdge(u: Int, v: Int) {
        graph[u].add(v)
    }
}

但是,当我创建DGraph的实例时,请在以下代码中使用它:

val graph = DGraph(5)
println(graph.graph.size)
graph.addEdge(0,1)

我发现在DGraph实例中没有初始化graph属性,我得到了IndexOutOfBoundsException。为什么会这样?

1 个答案:

答案 0 :(得分:1)

TL; DR override val构造函数参数中删除DGraph

您的代码秘密等同于以下Java伪代码:

class Graph {
    private final int n;
    private final List<MutableSet<Int>> graph;

    Graph(int n) {
        this.n = n;
        this.graph = someStuffThatCreatesAList(getN());
    }

    int getN() { return n; }

    // ...
}

class DGraph extends Graph {
    private final int n;

    DGraph(int n) {
        super(n);
        this.n = n;
    }

    int getN() { return n; }

    // ...
}

所以在Graph构造函数中,覆盖getN被调用。但是,子类成员尚未初始化,因此它返回默认值(0)。

删除override val后,您可以取消对getN的覆盖。