面向对象大三大特性:封装、继承、多态
封装
每个对象都包含它能进行操作所需要的所有信息,这个特性称为封装,因此对象不必依赖其他对象来完成自己的操作。
封装的好处:
- 良好的封装能够减少耦合
- 类内部的实现可以自由的修改
- 类具有清晰的对外接口
举例:
public class Cat(){
private String name;
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public String shout(){
return "我的名字叫" + name + " 瞄";
}
将小猫提炼成Cat类,其实就是在做封装,将名字封装成私有的,只能通过get方法操作。
继承
对象的继承代表了一种‘is-a’的关系,如果两个对象A和B,可以描述为‘B是A’,则表明B可以继承A。
如果子类继承于父类:
- 子类拥有父类非private的属性和功能
- 子类具有自己的属性和功能,即子类可以扩展父类没有的属性和方法
- 子类还可以以自己的方式实现父类的功能(方法重写)
举例:
小猫其实是一种动物,现实生活中有许多小动物,因此可以提炼出来一个父类-动物Animal
public class Animal {
protected String name;
public Animal(String name){
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
注:
- protected表示继承时,子类可以对基类有完全访问权。
- 子类无法继承父类的构造方法,只能通过
super()
关键字调用父类的构造方法。
举例,对cat类进行改造:
public class Cat extends Animal {
public Cat(String name){
super(name);
}
}
此时,可以使用Cat miao = new Cat("喵喵")
进行实例化,此时就是调用父类的构造方法进行实例化。
由于父类的name是protected类型,因此在同一个包下,可以通过miao.name
获取到喵喵
。
继承的优点是,继承使得所有子类公共的部分都放在了父类,使得代码得到了共享,就避免了重复,另外,继承可使得修改或扩展继承而来的实现都较为容易。
多态
多态表示不同的对象可以执行相同的动作,但要通过它们自己的实现代码来执行。
简单来说,加入有多个小动物,比如小猫、小狗,都会叫,将小动物们
多态存在的三个必要条件
- 继承
- 重写(也叫重构、覆盖)
- 父类引用指向子类对象
当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。
子类可以选择使用override关键字,将父类实现替换为它自己的实现,这就是方法的重写,或者叫方法覆盖。
举例(保留Animal类,改造Cat类):
public class Cat extends Animal{
public Cat(String name){
super(name);
}
@Override
public String getName(){
return "方法重写后的喵喵";
}
public String shout(){
return "我的名字叫" + name + " 瞄";
}
}
此时,Animal animal = new Cat("喵喵")
就是通过多态的方式示例化了一个Cat对象,但是这个Cat对象只能调用父类中有的方法,例如animal.getName()
,因为子类对该方法进行了重写,因此返回的结果是方法重写后的喵喵
,由于父类中没有shout()
方法,因此无法调用animal.shout()
方法。
个人感觉,Animal animal = new Cat("喵喵")
可以看成3步:
- 声明
Animal
对象,对象名为animal
- 实例化一个
Cat
对象Cat cat = new Cat("喵喵")
- 将
cat
对象向上转型为Animal
对象
这样就可以理解,为什么Animal类中没有的方法,cat对象就无法调用,而由于getName()
进行了方法的重写,因此还是会调用Cat
类中的方法。