关于java继承的问题请教

import java.util.HashMap;

class R extends HashMap<String, Object> {

    public R() {
        put("code", 0);
        put("msg", "success");
    }

    public static R ok() {
        return new R();
    }

    public static R ok(String msg) {
        R r = new R();
        r.put("msg", msg);
        return r;
    }
    
    // 这里不理解,为什么是super.put,而不是this.put
    public R put(String key, Object value) {
//        super.put(key, value);
        this.put(key, value);
        return this;
    }

}

public class R_test {
    public static void main(String[] args) {
        System.out.println(R.ok().put("a", "aaa"));
    }
}

有个地方不是很理解,就是put方法中,为什么要用super.put,不能用this.put。我的理解是,子类继承父类,可以调用父类的方法,但用this.put会报错,请问是为什么?

阅读 1.1k
1 个回答

this.put 是递归调用自己,super.put 是调用父类中定义的 put,是原功能实现。

这个类重载 put 大概只是为了能 return this 链式调用吧


回答 @Corvalds97

按理说应该是重写(overwrite),而不是覆写(override),但实际是 override。override 是覆写虚函数(Java 中不是 final 的默认是虚函数),理论上来说,override 函数要跟父类函数签名相同,虽然一般认为签名不含返回类型(调用时判断),但是 override 需要判断返回类型。所以下面这个代码是编译不过的

// Java

class One {
    public void test() { }
}

class Two extends One {
    public String test() { return ""; } 
}

但是题主的用例就很神奇,按理说 HashMap<K, V>put 是返回的 V 类型,而这里的 V 类型明明是 Object,为什么可以 override 成 R?—— 是因为 Java 泛型的类型擦除。类型擦除之后就都是 Object 了。

在 Java 中我不知道怎么写 overwrite,但是在 C# 中提供了 new 关键字来 overwrite。所以我可以用 C# 写一个 overwrite 的例子。

// C#

class One {
    public virtual void Test() {
        Console.WriteLine("one");
    }
}

class Two : One {
    public new void Test() {
       Console.WriteLine("two");
    }
}

class Three: One {
    public void Test() {
        Console.WriteLine("three");
    }
}

public class Program
{
    public static void Main()
    {
        One two = new Two();
        two.Test();     // one
        One three = new Three();
        three.Test();   // three
    }
}

上面的例子可以看到,overwrite 和 override 的不同。

至于 overload,主要是表示同名方法的不同签名(签名不含返回类型)

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题