JAVA || 继承
-
继承是什么? 有什么用?
像现实中的儿子和父亲。
基本作用: 子类继承父类,代码可以得到复用。
重要(主要)作用:因为有了继承关系,才有了后期的方法覆盖和多态机制。 -
继承的语法格式
class 类名 extends 父类名 {
类体;
} -
java的相关继承特性
1)B类继承A类,则称 A 为父类、基类、超类(superclass),称B类为类(subclass)、派生类、扩展类。
2)java中的继承只支持单继承,不支持多继承。C++支持多继承,这也是java体现简单性的一 点。换句话说,java中不允许这样写 class a extends b,c { }
3) 虽然java中不支持 多继承,但是有的时候会产生间接继承的效果。
例如: class C extends class B {}
class B extends class A {} 也就是说C直接继承了B,B间接继承了A。
4)java中规定,子类继承父类 ,除构造方法不能继承,剩下的都可以继承,但是私有的属性无法在子类中直接访问,可以间接访问。
5)java中的类没有显示的继承任何类,则默认继承object 类,objec类是Java语言提供的根类(老祖宗类),也就是说,一个对象与生俱来就有 object类型中所有的特征。
6)继承也存在一些缺点, 耦合度太高。父类修改,子类受牵连。
· 子类对象继承父类方法后,可以使用子类对象调用父类方法吗?
可以,当子类对象继承父类后,这个方法就属于子类了。
- 在实际开发中,满足什么条件可以使用继承?
· 凡是使用“is a” 描述的,都可以继承:
例如: cat is a animal
dog is a animal
bird is a animal
……
就算class A 和 class B有很多重复代码,但如果不能用 B is a A 来描述,也不能使用继承。
代码演示:
public class O001 {
public static void main(String[] args) {
Bird q = new Bird();
q.move();
}
}
class Animal{
public void move(){
System.out.println("动物在移动");
}
}
class Bird extends Animal {
}
程序输出结果:动物在移动
此时的程序并不能满足需求,程序最好输出 动物在移动,鸟儿在飞翔。
代码的优化涉及到方法的覆盖。
先上优化后的代码;
public class O002 {
public static void main(String[] args) {
monkey q = new monkey();
q.movee();
bird w = new bird();
w.movee();
dog e = new dog();
e.movee();
}
}
class Animals{
public void movee(){
System.out.println("动物在移动");
}
class bird extends Animals{
public void movee(){
System.out.println("🐦在飞");
}
}
程序输出结果:
(哈哈哈哈哈哈哈哈我也是偶然发现String可以打印emoji)
方法的覆盖
继承后,有些方法需要改进,有些方法根本用不了。
· 什么是方法覆盖?
方法的覆盖又叫做,方法重写,英语单词叫做:Override,Overwrite都可以。
比较常见的是:方法覆盖、方法重写、Override。
什么时候使用方法覆盖?
子类继承父类后,当继承过来的方法无法满足当前子类的业务需求时,子类有权利对这个方法进行重新编写,有必要进行“方法的覆盖”。
· 小结论:
当子类对父类继承过来的方法进行 方法覆盖后 ,子类对象调用该方法时,一定执行覆盖后的方法。
· 当我们怎么编写代码的时候,在代码级别上构成了方法覆盖呢?
条件一:两个类必须要有继承关系。
条件二:重写后的方法与原方法具有:
相同的返回值类型、相同的方法名、相同的参数列表。
条件三:访问权限不能更低,可以更高。
例如父类方法是protected,子类可以是public。
条件四:重写之后的方法不能比之前的方法抛出更多的异常,可以更少。
· 注意事项:(有关多态)
1. 方法覆盖只是针对于方法,与属性无关。
2. 私有方法无法覆盖。
3. 构造方法不能被继承,所以构造方法也不能被覆盖。
4. 方法覆盖只是针对于实例方法,对静态方法没有意义。
public class O002 {
public static void main(String[] args) {
monkey q = new monkey();
q.movee();
bird w = new bird();
w.movee();
dog e = new dog();
e.movee();
}
}
class Animals{
public void movee(){
System.out.println("动物在移动");
}
}
class monkey extends Animals{
//对move方法重写
//方法覆盖就是对继承的父类方法给覆盖掉,继承过来的方法就没了。
public void movee(){
System.out.println("🐒在爬");
}
}
class bird extends Animals{
public void movee(){
System.out.println("🐦在飞");
}
}
class dog extends Animals {
public void movee() {
System.out.println("🐶在跑");
}
}
输出结果:
Object
Object类是java默认的提供的一个类,Object类是所有类的父类,也就是说任何一个类的定义的时候如果没有明确的继承一个父类的话,那么它就是Object的子类
· 提供了那些方法?
很多哈哈哈哈,本文仅描述toString()方法。
· object里的 toString() 方法;
作用: 将“java对象” 转换为 “字符” 的形式。
大多数的java类toString()方法都是需要覆盖的,因为object中提供的toString()方法输出的是一个java对象的内存地址。
代码演示:
package Overrideee;
//调用toString方法 转换为字符串。
public class O003 {
public static void main(String[] args) {
Mydata q1 = new Mydata();
//System.out.println(q1.toString()); 输出结果不满意,对方法进行重写。
//Mydata继承的object的toString()方法, 输出Overrideee.Mydata@36baf30c,堆内存当中对象的内存地址。
System.out.println(q1.toString());
System.out.println(q1); //输出:2000年1月7日
//自动调用toString()方法。
Mydata q2 = new Mydata(2000,9,9);
System.out.println(q2); //输出:2000年9月9日
//自动调用toString()方法。
}
}
class Mydata{
private int year;
private int month;
private int day;
public Mydata(){
this(2000,1,7);
}
public Mydata(int year, int month, int day){
this.year = year;
this.month = month;
this.day = day;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
//重写的object中的toString方法
public String toString(){
return year + "年" + month + "月" + day + "日";
}
}
方法覆盖与方法重载的区别:
· 方法的重载:Overload。
· 什么时候使用方法的重载?
当在一个类中,方法功能相似,可以将方法名定义成一样的,这样代码美观、方便编程。
· 方法重载的条件:
1. 在同一个类当中。
2. 方法名相同,参数类表不同。
3. 方法的功能相似(个数、格式、类型)。
· 方法的覆盖:Override。
具体条件见上文。
最大区别:
方法重载发生在同一个类中。
方法覆盖发生在具有继承关系的不同类当中。
另附上我java原码位置,仅供参考(macos)。
/Library/Java/JavaVirtualMachines/jdk-14.jdk/Contents/Home/lib
第一次打开是有一个src.zip,解压后可即查看。