对象在 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
,而不是我期望的 2
或 4
?
通常我会假设,如果我 运行 对象 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 并完成方法调用。
我不明白,为什么 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
,而不是我期望的 2
或 4
?
通常我会假设,如果我 运行 对象 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 并完成方法调用。