抽象类与抽象方法
类到对象是实例化。对象到类是抽象
抽象类
1、什么是抽象类:
类和类之间具有的共同特征,但是不完全一样,有着自己的特色,
将这些共同的特征(方法)提取出来,形成的一个类就是抽象类
让这些具有共同特征的类去继承它
注意:这个类是抽象的,也就是"不存在的",所以无法实例化对象(不能new)
例子:
比如人类,我们单独创建一个类是无法完全具体的描述完人类的
比如肤色:有的是白色、有的是黑色、有的是黄色;
比如瞳孔颜色:有的棕色、有的蓝色、有的黑色...
显然我们不能说一个人的肤色又是黑色,又是白色;
一个人的瞳孔色即是棕色又是蓝色...
这是不合理的,但是这些特色却也有着共同点,比如肤色、瞳孔色,
虽然我们没法描述完所有肤色,但是我们可以说人类有肤色,
具体是什么肤色,我们让人类的子类去描述
比如黄种人、白种人、黑种人...每个子类都有着父类的特征,但也有着自己的特色
这里的人类就是一个抽象类,我么只是定义了一个模糊的概念,具体的实现细节我们并没有给出
人类的一个个特征就是一个个抽象方法,具体的实现细节都由继承的子类去描述
2、抽象类语法格式:
[修饰符列表] abstract class 类名{
类体;
}
注意:此处的修饰符列表只能为 public/protected 修饰
默认为 public 所以没有 default
不能为 private 否则子类无法继承
不能用 final 修饰,因为 final 和 abstract 是互斥的
final 修饰的类无法被继承,抽象类不被继承就没有意义
3、一个抽象类必须要被子类继承!否则这个抽象类是无意义的!
抽象类的子类可以是抽象类。也可以是非抽象类。
如果是非抽象类,代表父类的抽象方法必然被全部实现
如果是抽象类,代表父类的抽象方法'可能没有全部实现',可能子类有自己的抽象方法
'这里的实现,就是覆盖或者说重写,父类的抽象方法继承后并使其成为非抽象的方法'
4、抽象类属于什么类型?
抽象类也属于引用数据类型。
5、抽象类既然无法实例化,那么抽象类有构造方法吗?
抽象类有构造方法,这个构造方法是供子类使用的
6、抽象类中能有不抽象的方法吗?
可以,抽象类中不仅仅只存在抽象方法,也可以存在非抽象的方法
抽象方法
1、什么是抽象方法呢?
抽象方法表示没有实现的方法,没有方法体的方法
2、抽象类语法格式:
[修饰符列表] abstract [返回值类型] 方法名();
3、抽象方法特点是:
没有方法体,以分号结尾;
修饰符列表中有abstract关键字
4、抽象类中不一定有抽象方法,抽象方法必须出现在抽象类中。
例子
父类Animal
package com.blog.abstractTests;
/**
* @Author jinhuan
* @Date 2022/3/16
* 动物类:所有动物的父类
*/
public abstract class Animal {
/**
* 抽象方法: move() eat()
* 具体怎么实现我们没有说明
* */
public abstract void move();
public abstract void eat();
}
Animal的非抽象子类Dog
package com.blog.abstractTests;
/**
* @Author jinhuan
* @Date 2022/3/16
* 狗狗类:
* 一个非抽象类
* 继承了Animal这个抽象类,则必须实现其所有的抽象方法
*/
public class Dog extends Animal{
@Override
public void move() {
System.out.println("狗狗摇着尾巴走来啦!");
}
@Override
public void eat() {
System.out.println("狗狗在吃饭,吃的很香!!!");
}
}
Animal的抽象子类Bird
package com.blog.abstractTests;
/**
* @Author jinhuan
* @Date 2022/3/16
* Bird类:
* 一个抽象类
* 可以选择实现父类中的抽象方法,也可以不实现
* 如果本类不实现,那么其下级子类如果不是抽象类
* 则必须实现暂未实现的抽象方法
* 如果本类实现了父类中的其中一个抽象方法
* 那么其下级子类不用去实现该已经被实现的抽象方法
*
* 可以理解为
* 在一个家庭中:
* 父债子偿,子不能偿,孙子偿...
* 一旦某一代偿还了,则其后代就不用背负这个债务了
*
*/
public abstract class Bird extends Animal{
/**
* 只实现了一个抽象方法
* 那么其非抽象子类必须实现另一个方法
* */
@Override
public void move() {
System.out.println("很多鸟儿都用翅膀飞!");
}
}
Bird的非抽象子类LittleBird
package com.blog.abstractTests;
/**
* @Author jinhuan
* @Date 2022/3/16
*/
public class LittleBird extends Bird {
@Override
public void eat() {
System.out.println("鸟儿在吃饭!叽叽!喳喳!");
}
}
测试类
package com.blog.abstractTests;
/**
* @Author jinhuan
* @Date 2022/3/16
*
* 动物类的测试类
*/
public class AbTest01 {
public static void main(String[] args) {
//Animal animal = new Animal(); 不能直接创建抽象类对象
/**
* 创建狗狗对象并调用Animal的方法
* 因为狗狗类已经实现了Animal的所有抽象方法
* 所以都可以调用
* */
Animal dog = new Dog();
dog.eat();
dog.move();
System.out.println("========我是一个分界线===========");
/**
* 虽然bird类实现了Animal的抽象方法
* 但是它本质上还是一个用abstract修饰的抽象类
* 无法实例化
* */
//Bird bird = new Bird();
/**
* 虽然LittleBird类只实现了eat方法
* 但是其父类已经实现了move方法,子类继承了该方法就可以调用
* 但是由于LittleBird并没有重写该方法,所以咋调用的时候还是弗雷德实现细节
* */
Animal littleBird = new LittleBird();
littleBird.eat();
littleBird.move();
}
}
测试类运行截图
调用的时候还是弗雷德实现细节
* */
Animal littleBird = new LittleBird();
littleBird.eat();
littleBird.move();
}
}
###### 测试类运行截图
[外链图片转存中...(img-DuRuL15k-1647414469296)]