Java:[面向对象:继承,多态]
本文内容:
- 继承
- 多态
首发时期:2018-03-23
继承:
介绍:
- 如果多个类中存在相同的属性和行为,可以将这些内容抽取到单独一个类中,那么多个类(子类)无需再定义这些属性和行为,只要继承那个类(父类/超类/基类)即可。【比如,泰迪狗类也是狗类,狗的属性,泰迪狗也应该是有的,那么泰迪狗类在定义的时候就不必要添加那些与狗类重复的属性了,而是直接继承狗类即可。在多个狗类的子类(泰迪狗,二哈,柴犬)的时候,直接继承狗类可以省去很多代码,提高代码复用性。】
- 继承关系是通过extends来产生的,继承的格式:class 子类名 extends 父类名{}
- 子类可以直接访问父类中的非私有的属性和行为(因为私有的并非子父类共性属性、行为,父类并不一定只包含父子类共有的属性,还会包含自己应该有的属性,比如虽然哺乳类跟人类是父子类关系,但我们都能清楚,哺乳类有一些特别的特征我们人类是没有的)
- 继承的出现让类与类之间产生了关系,为第三个特征多态提供了前提。
- JAVA只支持单继承,不能有多个父类,但支持多实现(接口)(多继承可能因为多个父类中有同名变量或函数而发生调用的不确定性)
- JAVA支持多层继承
- 当子父类不同包时,子类无法继承父类的友好变量(默认无权限修饰),只能继承public 或 protected的。
class Person{ String gender="unknown";//为了测试继承,先赋值 int age; String family_address; private String children; } class Student extends Person{ } public class Demo { public static void main(String[] args) { Student st=new Student(); System.out.println(st.gender);//unknown // System.out.println(st.children);//报错,children是父类私有 } }
继承中的构造函数:
- 默认是有调用父类的构造函数的,如果想要显式调用父类的构造函数,可以使用super(参数列表)
- 为了测试有默认super()的例子
- 显示调用构造函数的例子:
- 注意:默认的super()在第一行,而用this调用构造函数时也必须在第一行,那么super()会默认在最终调用的构造函数的第一行。
class Person{ String gender="unknown";//为了测试继承,先赋值 int age; String family_address; private String children; Person(){ System.out.println("为了测试默认有super()"); } } class Student extends Person{ } public class Demo { public static void main(String[] args) { Student st=new Student(); } } -------------------结果: 为了测试默认有super()
class Person{ String gender; int age; String family_address; private String children; Person(String gender,int age,String family_address){ this.gender=gender; this.age=age; this.family_address=family_address; } } class Student extends Person{ Student(String gender,int age,String family_address){ super(gender,age,family_address); } } public class Demo { public static void main(String[] args) { Student st=new Student("男",18,"M78星云"); System.out.println(st.gender+st.family_address);//男M78星云 } }
继承中成员变量的隐藏和方法的重写:
- 对于子类中继承父类的成员变量,只要子类中对于同名的成员变量进行私有化,便能隐藏父类的成员变量。 【如果只是子类的成员变量是可见的,那么直接定义同名变量覆盖父类变量即可】
- 方法重写/覆盖:重写父类方法的时候不能降低方法的访问权限,也不能改变static修饰符。 【子类重写后的方法的权限必须大于等于父类的,非静态不能覆盖静态的,静态只能覆盖静态的】
- 重写就是子类中定义与父类中已有函数同名的函数,那么这个子类中的函数就将父类的函数覆盖了(不影响其他子类),当调用函数时,是调用子类中的该函数,而不是父类的。
- 如果想要使用被覆盖了的父类方法,要添加super
package 重写; class Person{ void show() { System.out.println("run in Fu"); } } class Student extends Person{ void show() { System.out.println("override in Zi"); super.show(); } } public class Demo { public static void main(String[] args) { Student st=new Student(); st.show(); //结果:override in Zi //run in Fu } }
注意:
- 当子父类出现同名变量,用super来区分
- 子类无法重写父类的private方法
- 用super.XXX来显式获取父类的成员变量或调用父类的方法
多态:
介绍:
- 指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。【或者说指父类的某个方法被子类重写时,可以各自产生自己的功能行为。】
- 一种体现是函数的重载;一种体现是函数的重写。
- 另一种一种显示形式:向上转型,子类转成父类对象,比如:
- 上转型对象不能操作子类新增的函数,但可以调用子类继承的成员变量或继承或重写的函数【注意的是不能调用子类隐藏父类的成员变量】。
使用:
向上转型:
package 多态_usage; class Animal{ int age=4; void show() { System.out.println("run in Fu"); } } class Tiger extends Animal{ int age=6; void show() { System.out.println("ao ao ao"); } } class Cat extends Animal{ void show() { System.out.println("miao miao miao"); } } public class Demo2{ public static void main(String args[]) { Animal a=new Tiger();//把老虎转型成父类-动物 Animal b=new Cat(); System.out.println(a.age);//4 a.show();//run in Zi b.show();//miao miao miao } }
注意:
-
成员变量子父类同名时,成员变量的调用看“.”所属的对象的类。比如是父类.成员变量那么就是父类的。