对象在 java 中评估

Object evaluating in java

我不明白,为什么 Java 会这样。

我有两个class,

Class答:

public class A {
  public String s = null;

  public A(int s) {
    this.s = "a";
  }

  public A(String s) {
    this.s = "b";
  }

  public int f(A p) {
    return 2;
  }
}

Class乙:

public class B extends A {
  public String s = "c";
  public B() {
    super(null);
  }
  public B (String s) {
    this (0);
    this . s = s ;
  }
  public B (int x) {
    super ("d");
  this . s = this . s + x ;
  }
  public int f (A p) {
    return 3;
  }
  public int f(B p) {
    return 4;
}

如果我知道有我的主class,我在其中运行下面的代码:

public class Test {
  Public static main(String[] args) {
    B b1 = new B("g");
    A ab = new B(6);
    System.out.println(ab.f(b1));
  }
}

为什么我得到的结果是 3,而不是我期望的 24? 通常我会假设,如果我 运行 对象 ab 的方法 f,并将对象 b1 作为参数给 f,它要么 return 2,要么不编译(因为唯一Class A 中的方法 f 使用对象 A 而不是对象 B),或者它将在 Class B 中寻找另一个方法 f,该方法使用对象 B 作为参数并执行该方法,其中如果程序应该 return 4.

这是相关声明

ab.f(b1)

将对象引用 b1 传递给方法这一事实无关紧要,因为这些方法中的 none 正在对传递的参数进行任何操作。这里的问题是应该调用 f() return 3 还是 2?它将 return 3 因为正在创建 B (A ab = new B(6);) 的实例和此 class B覆盖 f() 方法。

A ab = new B(6);有什么影响?

当你使用赋值符号=右边的superclass实例化对象时,你实际上是在扩大创建对象的类型(将 subclass 的对象变成 superclass 的对象)。如果 subclass 有新方法,则该对象将无法访问这些方法。只有在 superclass 中声明的方法是可访问的,并且通过多态性,覆盖的方法也是可访问的(如上面的示例所示)。但是,如果我们要向 class B

添加一个新方法
public void newMethod() {
    System.out.println("new method");
}

并修改了 Test class

public class Test {
    public static void main(String[] args) {
        B b1 = new B("g");
        A ab = new B(6);
        System.out.println(ab.f(b1));
        ab.newMethod(); // compile error
        b1.newMethod();
    }
}

newMethod 将无法访问实例 ab,但不会访问 b1。因此,ab 无法访问方法 f(B p),如下图所示。

我认为它在 class B 中调用了 returns 3 中的 f 方法,因为尽管 b1 属于 class B,但 class B 是一个子class 的 A. 因为 :

public int f (A p) {
   return 3;
}  

在另一个 f 方法之前,它首先检查那个。它说是A型的b1?答案是肯定的,因为所有 B 都是 A。因此它使用该函数 returns 3 并完成方法调用。