父类与子类的上下类型转换

简介: 父类与子类的上下类型转换

前言

       动物有共性的行为,例如吃。狗属于动物中的一类,对于“吃"这种行为,又有自己独特的见解,“吃狗粮”。当我们把“狗”上升到“动物”的概念,“狗”可以使用“动物”中的“吃”的行为,尽管在实践中,狗仍是进行“吃狗粮”的行为,在java中属于子类的向上转型;当我们把“动物”下沉到“狗”的概念,“动物”可以使用“狗”中的“吃狗粮”的行为,但前提是这个动物被认定为狗,毕竟不是所有动物都吃狗粮,在java中属于父类的向下转型。

一、上下类型转换是什么?


       向上转型:通过 new 关键字创建子类对象,赋值给 父类的引用变量,实现子类的向上转型

Parents a = new Child();
/*    Child类继承了Parents类
*     new关键字,创建了Child类的对象
*     赋值给了Parents类的引用变量 a
*     实现了 Child()对象的向上转型
*/

   向下转型:通过 new 关键字创建父类对象,强制转换,赋值给子类,实现父类的向下转型

Parents b = new Child();
/* new 关键字,创建了Child类的对象
*  赋值给了Parents中的引用变量 b
*  相当于创建了Parents对象
*  并且点明了Parents类和Child类的关系,Parents对象实际上为Child类的一个实例
*  进行强制转换时不会报错
*/
Child c = (Child)b;
/* 将引用变量 b 强制转换成 Child类的引用变量 c    
*  实现了Parents对象的向下转型
*/

  注意:

            1.父类与子类的上下类型转换,两个类之间,必须通过extends关键字,有继承关系

             2.向下转型时,父类不能直接通过 new 实例化 赋值给子类的引用变量,必须进行子类           的强制转换。举个例子,向上转型,我们可以把“鸭脖”上升到“食物”这一层次;向下转型,           我们不能直接将“食物”下降到“鸭脖”这一层次,因为食物是广泛的,你怎么知道它是鸭脖,           不是老鼠头呢?所以向下转型时,我们还要多一句“这就是鸭脖”,鸭脖 c =(鸭脖)b;

              3.向下转型时,Parents b = new Child(); 乍一看,这不是向上转型吗?是的,子类对象实例化,赋值给了父类,相当于创建了父类对象 b。向下转型时,少了这句话,就没有明确 b 实际上是子类的一个实例化对象,强制转换时,Child c =(Child)b;  会报错,不能强制转换

               4.无论是创建父类子类对象,还是进行上下类型转换的代码,都要在方法中才能用

               5.即使向上转型,转型为父类,调用父类方法,若被子类覆写过,仍然调用的是子类覆写过后的方法 ,因为本质上是子类实例化对象,赋值给了父类,归根到底还是子类对象  

二、使用方法

1.父类与子类的转换

       (1)创建父类 Food类,创建 nutrition()方法,num属性

package projectMy;
public class Food {
  void nutrition(){
    System.out.println("营养成分:糖类,蛋白质,脂肪,无机盐,维生素,水");
  }
  int num = 1;
}

(2)创建子类  DuckNeck类,覆写 nutrition()方法,创建 shape()方法

package projectMy;
public class DuckNeck extends Food{
  void nutrition() {
    System.out.println("营养成分:蛋白质,无机盐,脂肪,水");
  }
  void shape() {
    System.out.println("形状:长条脖子");
  }
}

(3) 创建Demo类,进行类的上下类型转换

               one.向上转型

package projectMy;
public class Demo {
  public static void main(String[] args) {
    Food food1 = new DuckNeck();
        //子类对象实例化,赋值给了父类,实现向上转型
    food1.nutrition();
        //调用父类方法,覆写过即为子类方法
        System.out.println("food1.num");
        //调用父类的属性
  }
}

      输出结果:

        问:输出结果是鸭脖的营养元素,不是父类中的营养元素,有没有发现,即使子类不进行向上转型,子类继承着父类。照样可以实现输出结果中的内容?


        答:向上转型的意义在于多态性,模块化,这种方法允许我们编写更多可以处理的泛型代码,多种类型的对象,而不必为每个对象编写单独的代码。

two.向下转型

package projectMy;
public class Demo {
  public static void main(String[] args) {
    Food food2 = new DuckNeck();
    DuckNeck duckNeck = (DuckNeck) food2;
    duckNeck.shape();
    duckNeck.nutrition();
    System.out.println(food2.num);
  }
}

输出结果:

           该传串代码,创建父类对象 food2,强制向下转型为子类 duckNeck对象,可以调用子类独有的shape()方法,覆写的方法,父类原本的属性。


           向下类型转换,可以用于生成初始化的对象,用户自定义选择,例如生成一个食物,用户可以根据自己的需要选择,将这个食物具体为面包,鸭脖等等,这时通过 向下类型转换 即可实现。

2.instanceof关键字

       instanceof关键字:判断父类与子类之间的继承关系是否正确

      语法:   子类对象名 instanceof 父类类名/接口名称

       实操展示:

boolean result = child instanceof Parents;
System.out.println(child instanceof Parents);
/* child 为子类对象   Parents 为类名
*  child 对象 是否为父类的继承对象
*  结果为布尔值,赋值到 result 对象
*/

  输出结果:true


        注意:


              1.instanceof关键字,只能在类与类是父类子类的继承关系时使用。类和类之间没有继承关系时,  用instanceof判断,会报错。

               2.如果是子类的父类的父类,判断子类是否继承父类的父类,可以使用instanceof关键字,返回 ture 值。

               假设 B类 继承 A类,C类 继承 B类

C c = new C();
system.out.println(c instanceof A);

  输出结果: true

               3. 可以理解为,instanceof关键字,判断父类和子类的关系是否颠倒,没有,返回true值;关系颠倒,返回false值。

总结

       以上就是父类与子类的上下类型转换,和instanceof关键字。如果对文章中“接口”概念不太熟悉,可以看up主空间的下一篇文章。

相关文章
C# 继承类中(父类与子类)构造函数的调用顺序
C# 继承类中(父类与子类)构造函数的调用顺序
|
2月前
|
C++
派生类的构造函数
派生类的构造函数
51 9
|
2月前
|
Java 程序员 C#
【类的应用】C#应用之派生类构造方法给基类构造方法传参赋值
【类的应用】C#应用之派生类构造方法给基类构造方法传参赋值
15 0
|
7月前
|
编译器 C++
C++程序中的派生类构造函数
C++程序中的派生类构造函数
68 1
为什么子类会调用父类无参的构造函数
为什么子类会调用父类无参的构造函数
|
编译器 定位技术
在父类的构造函数中调用虚函数为什么不能实现多态
在父类的构造函数中调用虚函数为什么不能实现多态
114 0
|
Java
获取java泛型类中的泛型类型
实现java中获取泛型类中的泛型类型的方法
273 0
C#编程-105:泛型继承之泛型类继承普通类
C#编程-105:泛型继承之泛型类继承普通类
107 0
C#编程-105:泛型继承之泛型类继承普通类
C#编程-106:泛型继承之普通类继承泛型类
C#编程-106:泛型继承之普通类继承泛型类
125 0
C#编程-106:泛型继承之普通类继承泛型类
子类到底能不能继承父类的私有属性?
继承就像是我们现实生活中的父子关系,儿子可以遗传父亲的一些特性,在面向对象语言中,就是一个类可以继承另一个类的一些特性,从而可以代码重用,其实继承体现的是is-a关系,父类同子类在本质上还是一类实体;子类通过继承父类的属性的行为,我们称之为继承。Java只支持单继承,不支持多继承。因为多继承容易带来安全隐患:当多个父类定义相同的功能,当功能内容不同的时候,子类对象不确定要运行哪一个,在Java中用另一种形式体现出来,就是接口的多实现。