java子类可继承父类静态方法,kotlin却不行?


#1

我该如何更简单的实现如下需求?
外部调用无需关心A类,只需要B.getString(B.b)即可

java实现:


class A {
    public static String getString(int value) {
        return String.valueOf(value);
    }
}

class B extends A {
    public static final int b = 1;
}

public class Test {
    public static void main(String[] args) {
        System.out.println(B.getString(B.b));
    }
}

kotlin实现:使用 companion object必须A、B都调用(A.getString(B.b)),并且其他实现方式都比java复杂很多


#2

我们只需要记住,继承是基于对象而言的,并不存在于静态成员中。

只不过在 Java 中,子类可以访问到父类的静态方法,因此给人一种“继承”的错觉,同样的静态方法也没有重写这一说法,例如下方的例子:

public class A {
    public static void staticMethod() {
        System.out.println("A.staticMethod");
    }

    public void method(){
        System.out.println("A.method");
    }
}

public class B extends A{
    public static void staticMethod() {
        System.out.println("B.staticMethod");
    }

    public void method(){
        System.out.println("B.method");
    }
}

public class Main {
    public static void main(String[] args) {
        B b = new B();
        b.staticMethod(); // B.staticMethod

        A a = b;
        a.staticMethod(); // A.staticMethod 不存在继承与重写的概念
        a.method(); // B.method  这才存在重写
    }
}

那么第二个问题,为什么在 Java 中子类 B 可以访问到父类的 A 静态成员,而 Kotlin 不行呢?

我们知道在 Kotlin 中声明静态成员是使用伴生对象来声明的,实际上伴生对象是在类中创建了一个静态的 Companion 对象作为静态成员的访问入口,真正静态的是 Companion 以及 Kotlin 为我们创建的 Companion 对象,而不是我们定义的静态成员。

子类如果不声明伴生对象,那么没有这个入口,如果声明了伴生对象,那么使用自己的 Companion 作为入口。

实际上,使用静态的 Companion 作为入口只有转换成 Java 后才能看到,我们在 Java 中调用 Kotlin 的静态成员时也是使用 Companion 来调用,我们同样可以通过这种方式访问到父类的 Companion。

// D extends C

C.Companion.getString(1);
D.Companion.getString(1);

但这是在 Java 中才能完成,在 Kotlin 中并没办法看到 Companion 这一入口,因此我们无法在 Kotlin 中调用父类的静态成员。


#3

你的回答很对,但只是说明了为什么不能访问。

事实上kotlin静态类是可以直接调用父类静态方法的(虽然只是编译前优化的效果),如下

open class A {

    companion object {

        fun getString(value: Int): String {
            return value.toString()
        }
    }
}

object B : A() {
    val testB = getString(1)//可以直接访问父类静态
}

fun main(args: Array<String>) {
    println(B.getString(1))//这里却报错
}

但其他类用子类却不给优化(B.getString(1)),不知道他们怎么想的


京ICP备16022265号-2 Kotlin China 2017 - 2018