面向对象技术的三大特性:继承性、多态性和封装性。
继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。
比如兔子和羊属于食草动物和食肉动物又是属于动物类。
所以继承需要符合的关系是:is-a,父类更通用,子类更具体。
虽然食草动物和食肉动物都是属于动物,但是两者的属性和行为上有差别,所以子类会具有父类的一般特性也会具有自身的特性。
子类拥有父类非private的属性,方法。
子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
子类可以用自己的方式实现父类的方法。
Java的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如A类继承B类,B类继承C类,所以按照关系就是C类是B类的父类,B类是A类的父类,这是java继承区别于C++继承的一个特性。
提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系)。
super关键字:我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。
this关键字:指向自己的引用。
对于构造器而言,它只能够被调用,而不能被继承
子类不能继承父类的构造器(构造方法或者构造函数),但是父类的构造器带有参数的,则必须在子类的构造器中显式地通过super关键字调用父类的构造器并配以适当的参数列表。
如果父类有无参构造器,则在子类的构造器中用super调用父类构造器不是必须的,如果没有使用super关键字,系统会自动调用父类的无参构造器。
就是如果父类含有有参的构造方法,子类必须用super关键字引用该构造器且必须将super此句写在该子类构造方法内的第一行。
如果父类含有无参的构造方法,子类不用写super语句但是会自动调用父类的无参构造器。
在子类与父类之间可以进行类型转换,其转换规则如下:
(1)隐式类型转换
用于将子类类型的数据转换为其父类型
例如:(假设有父类Employee和其子类Teacher)
Teacher tom= new Teacher();
Employee a= tom;
也可用强制类型转换运算符()进行转换:
System.out.println(((Employee)tom).workyear);
通过上面的语句,将子类类型的tom直接赋值给了父类类型的变量a。
(2)显式类型转换
用于将父类类型的数据转换为其子类型,这时如要加上 强制类型转换运算符()
例如:
Teacher tom= new Teacher();
Employee a= tom;
Teacher b=(Teacher)a;
上面语句将类型为父类的变量a强制转换为子类类型,在赋值给子类类型的变量b。
(3)如果两个类型不存在子类型与父类型之间的关系,则不能进行类型转换。
最后介绍子类的实例对象与父类的实例对象之间的关系
判断一个引用类型表达式所指向的实例对象是否是某种引用类型的实例对象可以通过instanceof运算符进行判断,其格式为:
引用类型表达式 instanceof 引用类型
运算结果返回的是一个布尔值。当引用类型表达式不是null并且所指向的实例对象是指定引用类型的实例对象时返回true,否则返回false。
可以将instanceof语句放在if判断条件等中。
多态性
不用类的对象收到相同消息执行不同操作
多态存在的三个必要条件
一、要有继承;
二、要有重写;
三、父类引用指向子类对象。
静态多态性
指的是在同一个类中同名方法在功能上的重载(overload)。要求在方法(成员方法或构造方法)声明上同名的方法具有不同的参数列表:
方法的参数个数不同、参数的数据类型不同或者参数的数据类型的排列顺序不同。
一般重载的方法具有相似的功能,这样增加程序的可读性,便于程序的维护。
动态多态性
覆盖(override)是子类对父类的允许访问的方法的实现过程进行重新编写, 方法名、返回值和形参都不能改变。即外壳不变,核心重写!
当需要在子类中调用父类的被重写方法时,要使用super关键字。
区别点 | 重载方法 | 重写方法 |
---|---|---|
参数列表 | 必须修改 | 一定不能修改 |
返回类型 | 可以修改 | 一定不能修改 |
异常 | 可以修改 | 可以减少或删除,一定不能抛出新的或者更广的异常 |
访问 | 可以修改 | 一定不能做更严格的限制(可以降低限制) |
封装性
是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。
基本思想:提供对外的通讯方式,封装内部的实现机制。
基本原则:
封装的实现:
1. 修改属性的可见性来限制对属性的访问(一般限制为private)
2. 对每个值属性提供对外的公共方法访问,也就是创建一对赋取值方法,用于对私有属性的访问