06-面向对象高级01
继承
让类与类之间产生关系(子父类关系),子类可以直接使用父类中非私有的成员
实现继承的关键字是:extends
继承的好处:
- 提高代码的复用性、维护性
何时用继承:
- 发现多个类中存在共性内容,并且存在 is…a 的关系
Q: 子父类中,如果出现了重名的成员变量,使用的时候会优先使用?
A:根据就近原则,优先使用子类的
packageextent;publicclassTest{publicstaticvoidmain(String[]args){Ziz=newZi();z.method();// 20}}packageextent;publicclassZiextendsFu{intnum=20;publicvoidmethod(){System.out.println(num);}}packageextent;publicclassFu{intnum=10;}如果要使用父类的,就需要使用 super 关键字来进行解决
this 调用本类成员
super 调用父类成员
packageextent;publicclassZiextendsFu{intnum=20;publicvoidmethod(){System.out.println(num);// 20System.out.println(this.num);// 20System.out.println(super.num);// 10}}Q:子类继承了父类之后,是否可以自己继续定义方法?
Override 重写——子类中重新定义父类已存在的方法
在继承体系中,子类可以继承到父类的方法,但有时子类并不想原封不动地继承父类的方法,而是想作一定的修改,这就需要采用方法的重写,方法重写又称方法覆盖
当然,也是可以定义自己的方法。
注意:
- 子类重写父类方法,需要保证方法声明完全一致(方法名,参数,返回值类型需要保持一致)
- 父类中私有方法不能被重写
- 子类重写父类方法时,访问权限必须大于等于父类
private 》 default 》 protected 》 public
继承的特点
Q:构造方法能否被继承?
A: 不可以,子类需要自己手动编写构造方法
Q:子类在初始化之前,是否需要先完成父类的初始化?
A:不需要,在所有的构造方法中,其实默认隐藏了一句话:super();通过这句代码,来访问父类的空参构造方法
packageextent;publicclassTeacher{Stringname;intage;}packageextent;publicclassStudentextendsTeacher{doublescore;}packageextent;publicclassTest{publicstaticvoidmain(String[]args){Students=newStudent();s.name="homes";System.out.println(s.name);}}Test 类中没有报错。
继承中的构造方法执行流程
然后访问的时候:
例子:
packageextent;publicclassEmployee{privateStringname;privateintage;privatedoublesalary;publicEmployee(){}publicEmployee(Stringname,intage,doublesalary){this.name=name;this.age=age;this.salary=salary;}publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.name=name;}publicintgetAge(){returnage;}publicvoidsetAge(intage){this.age=age;}publicdoublegetSalary(){returnsalary;}publicvoidsetSalary(doublesalary){this.salary=salary;}publicvoidwork(){System.out.println("员工在工作.....");}}packageextent;publicclassCoderextendsEmployee{publicCoder(){}publicCoder(Stringname,intage,doublesalary){super(name,age,salary);}@Overridepublicvoidwork(){System.out.println("姓名为"+getName()+", 年龄为"+getAge()+", 工资为"+getSalary()+"的程序员正在编写代码....");}}packageextent;publicclassManagerextendsEmployee{privatedoublebonus;publicManager(){}publicManager(Stringname,intage,doublesalary,doublebonus){super(name,age,salary);this.bonus=bonus;}publicdoublegetBonus(){returnbonus;}publicvoidsetBonus(doublebonus){this.bonus=bonus;}@Overridepublicvoidwork(){System.out.println("姓名为"+getName()+", 年龄为"+getAge()+", 工资为"+getSalary()+", 奖金为"+bonus+"的项目经理正在分配任务....");}}packageextent;publicclassTest{publicstaticvoidmain(String[]args){Codercoder=newCoder("张三",23,15000);coder.work();Managermanager=newManager("李四",24,18000,5000);manager.work();}}不一定必须加
@Override,但强烈建议加。不加的话: 程序可以正常运行,因为方法签名一致,Java 会自动判断为重写(Override)。
加上的话: 会让编译器帮你检查是否真的在重写父类方法。
**比如写错方法名,会报错 **
method does not override or implement a method from a supertype
this:代表本类对象的引用
super:代表父类存储空间的标识
二者都在争夺构造方法的第一行位置,所以二者不能共存
Object
所有的类,都直接或者间接的继承了Object类 (祖宗类)
Object 类的方法是一切子类都可以直接使用的,所以我们要学习 Object 类的方法
toString()
作用: 返回对象的字符串表示。
默认是返回当前对象在堆内存中的地址信息:类的全类名@十六进制哈希值
classStudent{Stringname;intage;}publicclassDemo03{publicstaticvoidmain(String[]args){Students=newStudent();System.out.println(s);// object.Student@2f4d3709}}- 开发中直接输出对象,默认输出对象的地址其实是毫无意义的
- 开发中输出对象变量,更多的时候是希望看到对象的内容数据而不是对象的地址信息。
😀开发中建议重写 toString 方法,以便展示对象属性信息
packageobject;classStudent{Stringname;intage;publicStudent(Stringname,intage){this.name=name;this.age=age;}@OverridepublicStringtoString(){return"Student{name='"+name+"', age="+age+"}";}}publicclassDemo03{publicstaticvoidmain(String[]args){Students=newStudent("张三",20);System.out.println(s);// Student{name='张三', age=20}}}final 关键字
final 关键字是最终的意思,可以修饰(方法,类,变量)
- 修饰方法:表明该方法是最终方法,不能被重写
- 修饰类:表明该类是最终类,不能被继承
- 修饰变量:表明该变量是常量,不能再次被赋值
一般用 全部 大写字母
细节补充:
1、 变量是基本类型:final修饰指的是基本类型的数据值不能发生改变
2、 变量是引用类型:final修饰指的是引用类型的地址值不能发生改变,但是地址里面的内容是可以发生改变的
3、 成员变量如果被final修饰,需要在构造方法结束之前完成赋值
finalintNUM=10;抽象类
抽象类是一种不能被实例化的类,通常作为父类使用,用于描述一类事物的共同特征。
- 抽象类中可以包含 普通方法、成员变量、构造方法以及抽象方法。
抽象方法:将共性的行为(方法)抽取到父类之后,发现该方法的实现逻辑。必须由子类进行实现(重写)。
- 抽象方法不可以存在方法体。就是
{} public abstract void eat();
定义抽象类和抽象方法使用的关键字是:abstract
注意事项:
- 抽象类不能实例化
- 抽象类存在构造方法
- 抽象类中可以存在普通方法
- 抽象类的子类
要么重写抽象类中的所有抽象方法
要么是抽象类
abstractclassAnimal{// 不能有方法体publicabstractvoideat();publicvoidsleep(){System.out.println("动物在睡觉....");}}classDogextendsAnimal{@Overridepublicvoideat(){System.out.println("狗在吃骨头.....");}}publicclassTest{publicstaticvoidmain(String[]args){Dogd=newDog();d.eat();// 狗在吃骨头.....d.sleep();}}abstract 关键字的冲突问题
- final:被 abstract 修饰的方法,强制要求子类重写,被 final 修饰的方法子类不能重写
- private:被 abstract 修饰的方法,强制要求子类重写,被 private 修饰的方法子类不能重写
- static:被 static 修饰的方法可以类名调用,类名调用抽象方法没有意义
模板设计模式
设计模式是软件开发中针对反复出现问题总结归纳出的通用解决方案。
模板设计模式:把抽象类整体就可以看做成一个模板,模板中不能决定的东西定义成抽象方法。让使用模板的类(继承抽象类的类)去重写抽象方法实现需求
模板设计模式的优势,模板已经定义了通用结构,使用者只需要关心自己需要实现的功能即可
