面向对象的特征之二:继承性
一、继承性的好处:
1.减少了代码的冗余,提高了代码的复用性。
2.便于功能的扩展。
3.为之后多态性的使用,提供了前提。
二、继承性的格式:class A extends B{}
A:子类、派生类、subclass
B:父类、超类、基类、superclass
1.体现:一旦子类A继承父类B以后,子类A中就获取了父类B中声明的结构:属性、方法。
另外:父类中声明为private的属性或方法,子类继承父类以后,仍然认为获取了父类中私有结构。只是因为封装性的影响,使得子类不能直接调用父类的结构而已。
2.子类继承父类后,还可以声明自己特有的属性和方法,实现功能的扩展。子类和父类的关系,不同于子集和集合的关系。
三、java中关于继承性的规定
java只支持单继承和多层继承,不允许多重继承
1.一个子类只能有一个父类
2.一个父类可以派生出多个子类
3.子类直接继承的父类称为直接父类,间接继承的父类称为间接父类。
四、方法的重写:
1.重写:子类继承父类以后,可以对父类中同名同参数的方法,进行覆盖操作。
2.应用:重写以后,当创建子类对象后,通过子类对象调用父类中的同名同参数的方法时,实际执行的是子类重写父类的方法。
3.重写的规定:
3.1约定俗称:子类中的叫重写的方法,父类中叫做被重写的方法。
3.2子类重写的方法的方法名和形参列表与父类被重写的方法的方法名和形参列表相同。
3.3子类重写的方法的权限修饰符不小于父类被重写的方法的权限修饰符。
特殊的:父类中用private修饰的不能被子类重写。
3.4返回值类型:
>父类被重写的方法的返回值类型是void,则子类重写的方法的返回值类型只能是void
>父类被重写的方法的返回值类型是A,则子类重写的方法的返回值类型可以是A类或A类的子类。
比如父类中有一个方法:
public Object a(){ return null; }
那么子类可以这么继承:
public String a(){ return null; }
3.5父类被重写的方法的返回值的类型是基本数据类型(比如:int),则子类重写的方法的返回值必须是相同类型的(int)。
4.子类重写的方法抛出的异常类型不大于父类被重写的方法抛出的异常类型。
注意:只有非static才考虑重写!
五、super关键字:
1.super可以理解为:父类的
2.super可以用来调用:属性、方法、构造器
3.super的使用:
3.1在子类的方法或者构造器中。通过“super.属性”或“super.方法”的方式,显式的调用父类中声明的属性或方法。但是通常情况下,我们习惯省略“super.”。
特殊时:当子类和父类中定义了同名的属性时,我们要想在子类中调用父类中声明的属性,必须显式的调用,表明调用的是父类中声明的那个属性。
4.super调用构造器:
4.1我们可以在子类的构造器中显式的通过使用“super(形参列表)”的方式,调用父类中声明的指定的构造器。
4.2“super(形参列表)”的使用,必须声明在子类构造器的首行!
4.3在类的构造器中,针对于“this(形参列表)”或“super(形参列表)”只能二选一,不能同时出现。
4.4在构造器的首行,没有显式的声明以上两种,则默认调用父类中的空参构造器。
4.5在类的多个构造器中,至少有一个类的构造器中使用了“super(形参列表)”,调用父类中的构造器。
5.子类对象实例化的全过程:
5.1从结果上看:子类继承父类以后,就获取了父类中声明的属性或方法。
创建子类的对象,在堆空间中,就会加载所有父类中声明的属性。
5.2从过程上来看:
当我们通过子类的构造器创建子类对象时,我们一定会直接或间接调用其父类的构造器,进而调用父类的父类的构造器,直到调用到java.lang.Object类中空参的构造器为止。正是因为加载过所有父类的结构,所有才可以看到内存中父类中的结构,子类对象才可以考虑进行调用。
具体表现如下图:
面向对象的特征之三:多态性
- 理解多态性:可以理解为一个事物的多种形态。
- 对象的多态性:父类的引用指向子类的对象(或子类的对象赋给父类的引用)
- 多态的使用:虚拟方法调用
有了对象的多态性以后,我们在编译期,只能调用父类中声明的方法,但在运行期,我们实际执行的是子类重写父类的方法。
总结:编译,看左边;运行,看右边。
4.多态性的使用前提:4.1类的继承关系 4.5方法的重写
5.为什么要有多态性呢?
举个例子:equals(Object obj)方法需要的是Object类型的参数,但是我们却从不new一个Object类型的对象吧,都是用的int、String等Object类的子类,这就是类的多态的使用嘛!
6.对象的多态性,只适用于方法,不适用于属性(编译运行都看左边)。
虚拟方法时什么意思,一张图弄清楚:
关于强制类型转换:
问题的引入:有了对象的多态性之后,内存中实际上是加载了子类特有的属性和方法,但是由于变量声明为父类类型,导致编译时,只能调用父类中声明的属性和方法,子类特有的属性和方法不能调用。
那么如何才能调用子类特有的属性和方法呢?
这个时候我们可以使用向下转型:强制类型转换符
例子和图形概念如下:
Person p1 = new Student();
Student s1 = (Student) p1;
这个时候s1就可以调用自己的属性和方法啦!