关于继承问题的讨论

class Base{
  private String name;
  private double size;
  public Base(double dax,String mz)
 {
  this.name=mz;
  this.size=dax;
 }
}
 
public class Sub extends Base{
 public String color;
 public Sub(double size,String name,String color)
 {
  super(size,name);
  this.color=color;
 }
 
 public static void main(String[] args)
 {
  Sub s=new Sub(5.6," 测试对象 "," 红色 ");
 }
}
注意到 Base name size 都是 private 的,子类中不可能继承,那么子类中 super(size,name) 调用父类构造函数
改变的是哪个对象的什么变量的值呢?是子类的对象还是父类的对象?
是不是每当创建子对象时系统默认创建相应的父对象???
执行了 Sub s=new Sub(5.6," 测试对象 "," 红色 "); 这句后,内存中有几个对象?属性值分别是什么?
 
讨论开始:
---------------------------------------------------------------------------------------------------------
(解答:)首先说明一点,对象只有一个,无论多少层的继承,都只有一个对象。
继承是相对于类而言,不想对于对象而言,类有继承的关系,对象是没有这个说法的。
private 会被子类所继承,不仅仅是 private ,如果子类有与父类同名的属性或者方法,同名的也会被继承,他们只是不能被访问,并不代表他们没有被继承下来。
 
 
问题补充:请问子类继承父类的属性和方法,则创建子类对象时不管是 private 的还是 public 的是否都在内存中实际存在呢?
 
 
解答:必须,否则你的对象还怎么能正常工作呢?要知道基类的所有方法,基本上都是建立在那些 private 属性和 private 方法上开展工作的。
 
之所以 private ,其实本质上是就是为了保护基类自己的运行环境不被随意调整,所以让你不可见。
 
解答:子类中不可能继承,这句话是错的。私有成员是不能在其他地方直接访问。子类继承父类的所有东西。当创建子类对象时,内存中会开辟一个父类的空间(并不是创建一个父类对象,也就是说从始至终只有一个对象),所以现在回答楼主问题。
 
问:改变的是哪个对象的什么变量的值呢?
答: super 方法调用父类构造方法,改变子类实例 s size name 值。
 
问:是子类的对象还是父类的对象?
答: s 是子类对象。所以改变的是子类对象。
 
问:是不是每当创建子对象时系统默认创建相应的父对象???
答:不是。
 
问:执行了 Sub s=new Sub(5.6," 测试对象 "," 红色 "); 这句后,内存中有几个对象?属性值分别是什么?
答:一个。值的话,应该不用说了吧。。。
 
继续问:既然子类不能访问父类中 private 修饰的成员,那么继承过来的 private 成员有什么用 ?
 
9 楼其实说了,我再换个方式解释下。
 
所继承过来的 private 成员,不是直接供子类使用的。而是供父类所提供方法来使用的。
 
比如你的父类如果是这样:
Java code
 
class Base{
  private String name;
  private double size;
  public void setSize(double newSize) {
    this.size = newSize;
  }
}
 
那么如果你的子类没有完整继承 private size 的话,那么子类的实例(对象)调用 setSize 方法时, JVM 怎么办?所以必须要有基类完整的内容,基本是那些已经被子类重写的函数,也仍然会有。
 

下面引用《java 编程思想》的一段话:
由于这儿涉及到两个类――基础类及衍生类,而不再是以前的一个,所以在想象衍生类的结果对象时,可能会产生一些迷惑。从外部看,似乎新类拥有与基础类相同的接口,而且可包含一些额外的方法和字段。但继承并非仅仅简单地复制基础类的接口了事。 创建衍生类的一个对象时,它在其中包含了基础类的一个“子对象”。这个子对象就象我们根据基础类本身创建了它的一个对象。从外部看,基础类的子对象已封装到衍生类的对象里了。
当然,基础类子对象应该正确地初始化,而且只有一种方法能保证这一点:在构建器中执行初始化,通过调用基础类构建器,后者有足够的能力和权限来执行对基础类的初始化。在衍生类的构建器中,Java会自动插入对基础类构建器的调用。

 
从一开始, Java 的语法结构就会把人往一个错误的方向去引领 ( 或许这不是一种错误,因为 Java 本身是希望程序员去这么思考与应用,但是它是与实际执行是背离的 ) super 在语法层次,看上去就像父类对象的指针,但是事实却不是,在构造函数第一句的 super 指的是一个父类的构造方法,即使你不加 super ,那么虚拟机会自动添加 super() 在任何构造方法的第一句,也就是说父类构造方法一定会被执行。而普通方法中的 super.xxx 中的 super 也不是父类的对象,而是一个引用父类类型的一个指针,其实无论 super 还是 this ,把它理解为指向对象其实是并不太合适的。更好的理解应该是指向当前类型,因为无论怎么样,对象只有一个。
另外,方法与属性其实是有区别的,对象的成员属性是多个的,他会与对象一起存放在堆中,但是方法都是只有一个 ( 至少在一个域中是如此,想要了解域,你要学习类的装载机制、类型管理与 jdk 安全机制,这个你可以自己去学习 ) ,方法都只属于类,虽然很多时候动态看上去都属于某个对象,恰恰相反,是这个对象属于这个方法。因为静态方法与动态方法唯一的一个区别,就是一个不能用 this 一个能用 ( 当然,调用的指令与 jvm 方法搜索机制都不同,但是这些不能决定他们的本质,关于这点你可以去查看 jvm 指令集说明 ) ,动态方法只是有第一个默认参数,当前对象 this ,而静态方法没有这个缺省对象,我只介绍到这里,更深入的,你还是自己去看吧,如果你真的想要理解 java 底层,你就要完全跳出 java 的语法对你的影响,因为 jvm C 语言开发的,他的字节码执行逻辑是类汇编,用面向对象去理解这些东西,会出现偏差那就是很正常的事情了。

你可能感兴趣的:(java)