一行代码突然挡住了菜鸟前进的道路:father f=new son();
貌似牛头不搭马嘴的样子,自己一下子都懵了,不同数据类型的值还能互相赋值的吗,以前的学基本数据类型里提到过数据类型的转换,记得几行很经典的代码(不过是反面教材):
short sh=5;
sh=sh-3;
敲进“伊柯丽不是”里一运行,它就嗡嗡的又哭又闹的提示说“类型转换有误”。苦思闷想一早上,终于有点明白了,原来sh-3已经是int数据类型的值了,赋值给一个shor类型的sh当然不愿意了。
于是再鼓捣一下,换个马脸:
sh-=3;
再扔进“伊柯丽不是”里运行,它不闹,说明这是可以,这会轮到我哭闹了。为什么这样就没错呢?拽着咱们班的“大神”蹲在“伊柯丽不是”前叫他来一下子,他也头晕。这下可好,把大神难倒,只有寻找民间偏方,去问那些平时不学习但期末考试成暴发户的同学,最终得到一个结论:sh-=3里已经包含强制类型转换。恩···装着接受这个解释
而现在又出新难题。为什么可以子类的实例赋值给父类的对象?这是那个门派的阴招呢?为什么要这样耍出来呢?有什么好处?
都“度娘”里折腾了一番,得到一条重要的消息:
1)子类里有一个区域放的父类的实例,子类内存区里有一个this指针,指向了这个内存区里包括的父类实例区,当把引用付给父类时,是把子类内存区里面的父类实例区域的引用给了父类的实例.
2)super相当于指向父类示例的一个指针; 子类只保存子类的信息和super指针; 当JVM加载一个子类的时候也会把它的父类一同加载的,子类内部通过super保存父类的一个引用
也就是说在son类的内存区里,有一个区域放着father类的实例。取名为super;super里保存着指向father类的地址(这也是为什么在子类中可以用super()来代替父类的原因)。
因此真相大白了,father f=new son();当son类继承了father类之后,它已经保存了指向father类的地址信息,此时即是用父类引用指向子类对象 ,这是一种向上转型,当父类需要使用子类功能时(父类被子类覆盖的方法)就可以将子类对象上转给父类引用。
不仅仅是父类可以指向子类的对象,只要是祖先类都可以指向子类的实例。典型情况,Object是所有类的祖先类,所以Object类型的对象引用可以指向任何对象。例如下面的代码:
Object o = new son();
那么把父类引用指向子类对象的好处是什么呢?
其实,父类引用指向子类对象就是java的多态。也叫动态绑定。
把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化。 赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。也就是说,父亲的行为像儿子,而不是儿子的行为像父亲
分享到:
相关推荐
子类的构造函数可以接受一个父类对象作为参数,然后在构造函数内部,使用成员变量直接赋值或者通过 `base` 关键字调用父类的构造函数。例如: ```csharp public class Parent { public int Id { get; set; } ...
3. **变量隐藏**:如果子类和父类有同名的实例变量,子类变量会“隐藏”父类变量。通过父类引用访问这些变量时,实际访问的是父类的变量,而非子类的。 4. **类型转换**:虽然父类引用可以指向子类对象,但反过来...
如果一个类继承一个父类,那么子类会拥有父类所规定的所以成员 子类还可以拥有父类没有的独有成员 ...声明父类变量,实例化子类对象 Person p = new Student(); p.personshow();//说明不可以调用子类的方法,还是父类
这是因为子类实例变量是在父类实例变量的基础上增加的,因此需要先初始化父类的实例变量。 接下来,关于访问修饰符的影响。在实例化过程中,如果父类的构造器是私有的(private),那么子类无法直接访问,除非在...
通过这种方式,我们可以确保即使对象是子类实例,调用的也是父类的虚函数实现。 总结来说,C++中的`指针`和`引用`提供了灵活的数据操作方式,而`虚函数`则是实现多态性的重要工具。理解子类对象不能直接调用父类虚...
子类对象可以赋值给父类类型的引用,但此时该对象实际上仍然是一个子类实例,只是从编译角度看作父类类型。这种特性称为“多态”。 示例代码如下: ```java public class SuperClass { protected String ...
由于 Java 语言的多态性使得可以用一个子类的实例赋值给一个父类的变量,而在一些情况下需要判断变量到底是一个什么类型的对象。 在 Java 中,数组也可以是同类收集(homogenous collections)或异类收集...
java 静态_非静态 字段_方法_代码块 子类父类构造_初始化顺序! 三个class 让你清清楚楚 第一个class java代码如下: package initialOrder; class Parent { // 静态变量 public static String p_StaticField...
在 Java 中,每个子类对象都是父类对象的实例,因此可以将子类对象赋值给父类变量。但是,反之不一定成立,即父类对象不一定可以赋值给子类变量。这是因为父类变量可以引用子类对象,但是子类变量只能引用子类对象。...
在子类实例中调用该方法时,将执行子类的方法,而不是父类的。这是因为子类的对象在内存中包含了父类的所有属性和方法,但子类的方法优先级更高。 4. **静态初始化块**: - 静态初始化块在类加载时执行,而不是在...
这里,`__init__`方法被定义为类`Father`的构造函数,它接受一个参数`name`并将其存储在实例变量`self.name`中。 #### 二、子类不重写父类的构造函数 如果子类没有定义自己的构造函数(即没有定义`__init__`方法)...
判断一个类是否为另一个类的子类或父类可以使用 Class 对象的 isAssignableFrom() 方法,该方法返回一个布尔值,表示该类是否为另一个类的子类或父类。 在 Java 中,我们可以使用反射机制来获取类中的成员变量、...
这是面向对象编程中的一个基本规则,即子类实例化时会先执行父类的构造方法。如果父类还有父类,这个过程会一直向上递归,直到最顶层的类(Object类)。 2. **类成员变量初始化**:在所有父类构造器执行完毕后,...
这是因为C#在创建子类实例时,会自动调用父类的无参构造函数(如果没有指定特定的构造函数)。 如果父类没有无参构造函数,如下面的情况: ```csharp public class Person { public Person(string name) { ...
- **子类类型变量访问:** 子类类型引用可以访问到子类的所有实例变量,包括隐藏的父类变量和子类特有的变量。 3. **内存分配:** - **父类部分:** 当创建一个子类对象时,内存会为父类部分和子类部分都分配空间...
变量和方法覆盖和隐藏的不同:一个类的实例无法通过使用全局名或者强制自己转换为父类型,以访问父类中被隐藏的方法,然而强制转换子类为父类型之后,可以访问父类中被隐藏的变量。另外静态方法不能覆盖父类的实例...
标题“学学Python_43类的成员02 调用父类构造函数”指的是在子类中调用父类的初始化方法,以确保子类实例化时,父类的数据成员也能得到正确初始化。描述中提到的文章链接是一个CSDN博客文章,详细介绍了这个问题。 ...
Java子类调用父类的方法中包含子类重写的实例方法 Java 子类调用父类的方法中包含子类重写的实例方法是 Java 编程语言中一个重要的概念。下面我们将详细介绍这个概念,包括相关的知识点和示例代码。 子类调用父类...
在Java中,我们可以通过父类的引用变量来指向子类的对象,这种现象被称为“向上转型”(Upcasting)。例如: ```java class Animal {} // 父类 class Cat extends Animal {} // 子类 public class Test { public ...
程序中描述了子类对象构建调用父类的构造方法,以及类变量和实例变量创建的不同过程