Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/356.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 多态性与遗传_Java_Oop_Inheritance_Polymorphism - Fatal编程技术网

Java 多态性与遗传

Java 多态性与遗传,java,oop,inheritance,polymorphism,Java,Oop,Inheritance,Polymorphism,在这种情况下: class A{ public int x = 4; public void s3(){ x = 3; } public void f(){ x = 8; s3(); } } class B extends A{ public int x = 5; public void f(){ x = 10; s3(); } } A a = new B(); B b = (B) a

在这种情况下:

class A{
   public int x = 4;
   public void s3(){
      x = 3;
   }
   public void f(){
      x = 8;
      s3();
   }
}

class B extends A{
   public int x = 5;
   public void f(){
      x = 10;
      s3();
   }
}

A a = new B();
B b = (B) a;
a.f();
System.out.println(b.x);
System.out.println(a.x);
public void s3(){
      x = 3;
   }

a.f()
调用类
B
f()
,然后
f()
在赋值后调用
s3()
函数。此时,
s3()
仅在
A
中定义,当它将值3赋给
x
时,
x
是类
A
拥有的变量的副本。为什么
s3()
不使用
B
中声明的
x
?理论上,
B
不应该有它自己的
s3()
函数的副本继承自
A
?(因此,从
B
中的
A
继承的
s3()
应该使用
B
中声明的
x

您对继承中应该做什么有误解<代码>扩展是一个明智选择的保留字。B扩展A的目的是说B是A的一个子集,具有附加属性。你不应该在B中重新定义
x
;A应处理
x
。通过在子类中重新定义
x
,可以隐藏超类的字段
x
(即使
x
引用了不同的变量类型,也是如此)

10来自打印b的x,通过调用
a.f()
将其分配给10,然后调用
s3()
,这就是第三个示例打印3的原因。要了解我的意思,请看以下内容:

  public void f()
   {
      x = 10; //sets B's x to 10
      s3();  //calls A's s3(), which sets A's x to 3.
   }

你对你在继承中应该做什么有一个误解<代码>扩展是一个明智选择的保留字。B扩展A的目的是说B是A的一个子集,具有附加属性。你不应该在B中重新定义
x
;A应处理
x
。通过在子类中重新定义
x
,可以隐藏超类的字段
x
(即使
x
引用了不同的变量类型,也是如此)

10来自打印b的x,通过调用
a.f()
将其分配给10,然后调用
s3()
,这就是第三个示例打印3的原因。要了解我的意思,请看以下内容:

  public void f()
   {
      x = 10; //sets B's x to 10
      s3();  //calls A's s3(), which sets A's x to 3.
   }

因为它是一样的。对象没有两个副本(“实例”),只有一个副本

由于您创建的是一个
B
实例(
new B()
),它将使用
B
中定义的方法。当然,当
B
中没有定义方法时,它将使用超类方法实现


因此,您只有一个
x
属性,而
s3
强制将其设置为
3
。它工作正常。

因为它是一样的。对象没有两个副本(“实例”),只有一个副本

由于您创建的是一个
B
实例(
new B()
),它将使用
B
中定义的方法。当然,当
B
中没有定义方法时,它将使用超类方法实现

因此,您只有一个
x
属性,而
s3
强制将其设置为
3
。它工作正常

为什么s3()不使用B中声明的x

通常,父类中的方法无法看到子类中的成员变量

我认为这样做:

B b = new B();
b.f();
这足以再现你的一部分困惑。下面是f()在B中的样子:

class B extends A{
   public int x = 5;
   public void f(){
      x = 10;
      s3();
   }
}
f()相当于:

   public void f(){
      this.x = 10;
      this.s3();
   }
   public void f(){
      b.x = 10;
      b.s3();
   }
public void s3(){
      this.x = 3;
   }
public void s3(){
      b.x = 3;
   }
因此,调用b.f()意味着f()相当于:

   public void f(){
      this.x = 10;
      this.s3();
   }
   public void f(){
      b.x = 10;
      b.s3();
   }
public void s3(){
      this.x = 3;
   }
public void s3(){
      b.x = 3;
   }
接下来,在中的s3()方法内部发生了什么?s3()如下所示:

class A{
   public int x = 4;
   public void s3(){
      x = 3;
   }
   public void f(){
      x = 8;
      s3();
   }
}

class B extends A{
   public int x = 5;
   public void f(){
      x = 10;
      s3();
   }
}

A a = new B();
B b = (B) a;
a.f();
System.out.println(b.x);
System.out.println(a.x);
public void s3(){
      x = 3;
   }
这相当于:

   public void f(){
      this.x = 10;
      this.s3();
   }
   public void f(){
      b.x = 10;
      b.s3();
   }
public void s3(){
      this.x = 3;
   }
public void s3(){
      b.x = 3;
   }
“this”是调用该方法的对象,从f()的最后一个示例中可以看到它是b。因此s3()相当于:

   public void f(){
      this.x = 10;
      this.s3();
   }
   public void f(){
      b.x = 10;
      b.s3();
   }
public void s3(){
      this.x = 3;
   }
public void s3(){
      b.x = 3;
   }
所以b.x被3覆盖了…嗯,不那么快

B的一个实例也从A继承了一个x,只是在B的内部,恰好B的x从A阴影x。因此,B中的f()方法从B赋值给x。在s3()内部,B从A得到的x不再阴影,而就A而言,只有一个x——来自A的x。换句话说,b.x的查找采用不同的路径,具体取决于该语句出现在哪个类中

执行s3()后,最终结果是b有两个x,具有两个不同的值。在B中的方法内部,B中的x将可见,在A中的方法内部,A中的x将可见。在B中的方法中,可以使用super从A获得x

理论上,B不应该有自己的s3()函数的副本继承自A

不要用复制品来思考。考虑从类到类的指针,以及从类到查找表的指针。通常在计算机编程中,每个实例都有自己的实例变量,但方法由类中的所有实例共享

为什么s3()不使用B中声明的x

通常,父类中的方法无法看到子类中的成员变量

我认为这样做:

B b = new B();
b.f();
这足以再现你的一部分困惑。下面是f()在B中的样子:

class B extends A{
   public int x = 5;
   public void f(){
      x = 10;
      s3();
   }
}
f()相当于:

   public void f(){
      this.x = 10;
      this.s3();
   }
   public void f(){
      b.x = 10;
      b.s3();
   }
public void s3(){
      this.x = 3;
   }
public void s3(){
      b.x = 3;
   }
因此,调用b.f()意味着f()相当于:

   public void f(){
      this.x = 10;
      this.s3();
   }
   public void f(){
      b.x = 10;
      b.s3();
   }
public void s3(){
      this.x = 3;
   }
public void s3(){
      b.x = 3;
   }
接下来,在中的s3()方法内部发生了什么?s3()如下所示:

class A{
   public int x = 4;
   public void s3(){
      x = 3;
   }
   public void f(){
      x = 8;
      s3();
   }
}

class B extends A{
   public int x = 5;
   public void f(){
      x = 10;
      s3();
   }
}

A a = new B();
B b = (B) a;
a.f();
System.out.println(b.x);
System.out.println(a.x);
public void s3(){
      x = 3;
   }
这相当于:

   public void f(){
      this.x = 10;
      this.s3();
   }
   public void f(){
      b.x = 10;
      b.s3();
   }
public void s3(){
      this.x = 3;
   }
public void s3(){
      b.x = 3;
   }
“this”是调用该方法的对象,从f()的最后一个示例中可以看到它是b。因此s3()相当于:

   public void f(){
      this.x = 10;
      this.s3();
   }
   public void f(){
      b.x = 10;
      b.s3();
   }
public void s3(){
      this.x = 3;
   }
public void s3(){
      b.x = 3;
   }
所以b.x被3覆盖了…嗯,不那么快

B的一个实例也从A继承了一个x,只是在B的内部,恰好B的x从A阴影x。因此,B中的f()方法从B赋值给x。在s3()内部,B从A得到的x不再阴影,而就A而言,只有一个x——来自A的x。换句话说,b.x的查找采用不同的路径,具体取决于该语句出现在哪个类中

执行s3()后,最终结果是b有两个x,具有两个不同的值。内部方法一