面向对象的三大特性
约 968 字大约 3 分钟
2025-02-24
封装
- 封装更容易地修改类的内部实现,无需修改该类的代码
继承
- 继承就是子类继承父类的属性和方法,使得子类对象(实例)具有父类的属性和方法,或子类从父类继承方法,使得子类具有父类相同的方法。
- 多继承方式
- 接口、内部类、多层继承
- 如果子类的构造方法中没有显示地调用父类构造方法,则系统默认调用父类无参数的构造方法。
- 子父类初始化顺序
- 父类中静态成员变量和静态代码块
- 子类中静态成员变量和静态代码块
- 父类中普通成员变量和代码块,父类的构造方法
- 子类中普通成员变量和代码块,子类的构造方法
多态
多态的前提条件有三个:
- 子类继承父类
- 子类重写父类的方法
- 父类引用指向子类的对象,即:
父类类名 引用名称 = new 子类类名();
多态与向下转型
- 当父类引用指向的是父类对象时,这时候强转就会报错
向上转型和向下转型
class Animal { void makeNosie(){ system.println.out("noise"); } }
class Dog extend Animal { @overried void makeNosie(){ system.println.out("汪汪"); } void growl(){ system.println.out("growl"); } }
//启动类 public static void main(String[] args){ Animal animal = new Dog(); animal.makeNosie(); // 输出为汪汪 animal.growl();//运行正确 doAnimalStuff(animal); } //下面写法,就不需要为每个动物创建,只需要通过向上转型即可 void doAnimalStuff(Animal animal){ animal.makeNosie(); }
//启动类2,向下转型 public static void main(String[] args){ Cat cat = new Cat(); doAnimalStuff(animal); } //下面写法,就不需要为每个动物创建,只需要通过向上转型即可 void doAnimalStuff(Animal animal){ animal.makeNosie(); Dog dog = (Dog)animal;//此时会报类型转换错误 dog.growl(); //解决方案,通过验证类型 if(animal instanceof Dog){ Dog dog = (Dog)animal; dog.growl(); } }
多态实现方式
场景:加入有一个老师,需要给每个学生评价
不使用多态的实现
- 一个老师Student,老师Teacher,学生A,学生B
public abstract class Student { public void evaluate() { System.out.println("系统评价!"); } }
public class Teacher { public void evaluateTeacher(A a) { a.evaluate(); } public void evaluateTeacher(B b) { b.evaluate(); } }
public class A { public void evaluate() { System.out.println("系统评价A!"); } }
public class B { public void evaluate() { System.out.println("系统评价B!"); } }
使用多态实现,只需要修改Teacher类
public class Teacher { public void evaluateTeacher(Sudent s) { s.evaluate(); } }
陷阱:“重写”私方法
- 因为private对于派生类来说是隐藏的,private方法可以当作是final,因此派生类中的f()并不是重写,如果使用@override可以检查到错误
package polymorphism; public class PrivateOverride { private void f() { System.out.println("private f()"); } public static void main(String[] args) { PrivateOverride po = new Derived(); po.f(); } } class Derived extends PrivateOverride { public void f() { System.out.println("public f()"); } }
陷阱:属性与静态方法
- 静态方法不具有多态性
如果遇到派生类扩展的方法在基类中没有,这时需要向下转型,但是遇到下面这种情况。会报类型错误
public class RTTI { public static void main(String[] args) { Useful[] x = { new Useful(), new MoreUseful() }; x[0].f(); x[1].g(); // Compile time: method not found in Useful: //- x[1].u(); ((MoreUseful) x[1]).u(); // Downcast/RTTI 这里是父类指向的是子类对象 ((MoreUseful) x[0]).u(); // Exception thrown // 因为父类指向的是父类对象 } }
为什么java作者不支持多继承机制
- 引入多继承机制会带来“钻石问题”,就是会出现一个类继承多个父类,会让继承的深度更加混乱
总结
上述链接如下:深入理解Java三大特性:封装、继承和多态 | 二哥的Java进阶之路、docs/book/09-Polymorphism.md · 码到成攻/Java编程思想_第5版_中文 - Gitee.com