一、抽象类基本介绍
1.抽象类的概念
在我们类和对象学习中,所有的对象都是依赖于类来实现,比如狮子是一种动物,海豚是一种动物。
class Animal{
public String name;
public Animal(String name) {
this.name = name;
}
public void living(){
System.out.println(name+"生活");
}
}
class Lion extends Animal{
public Lion(String name) {
super(name);
}
@Override
public void living() {
System.out.println(name+"在陆地生活");
}
}
class Dolphin extends Animal{
public Dolphin(String name) {
super(name);
}
@Override
public void living() {
System.out.println(name+"在海洋生活");
}
}
public class Main {
public static void breath(Animal animal){
animal.living();
}
public static void main(String[] args) {
// Animal animal1=new Cat("猫咪");
// Animal animal2=new Fish("海豚");
//
// animal1.living();
// animal2.living();
breath(new Dolphin("海豚"));
breath(new Lion("狮子"));
}
}
我们分别利用方法传参的 和 直接赋值两种向上转型的方法实现了多态,但是这个Aniaml在我们没有实现继承之前我们知道他到底是哪一种动物吗,没有。它无法形容任何一种动物是如何生存的。
看图⬇️
矩形、圆形、三角形都属于图形这个类,形成了继承关系。子类需要重写父类的方法,所以也继承了draw()这个方法。但是图形类他没有办法实现这个draw方法,因此我们可以将这个图形Shape类设计为抽象类。
抽象类的定义:如果一个类当中没有足够的信息来描述一个对象,就需要把这个类设计为抽象类
二、抽象类的特性
1.抽象类和普通类的区别
抽象类和普通的区别主要在于以下两点
1.抽象类不能被实例化
2.抽象类当中,可以包含非抽象方法和抽象方法,但是普通类只能包含非抽象方法
//1.被abstract修饰的类称为抽象类
//2.抽象方法可以不用方法体
//3.抽象类可以包含属性以及普通方法
abstract class Shape{
abstract void draw();
public void func(){
System.out.println("抽象类可以包含普通方法");
}
public double area;
}
区别1: 在给抽象类实例化的时候出现了错误,提示我们抽象类是无法实例化的。
区别2:
抽象类可以包含抽象和非抽象方法
普通类只能包含非抽象方法,如果想要包含抽象方法就必须将类修改成抽象类,并且将普通方法用关键字abstract修饰
2.对比抽象与非抽象方法
在我们的抽象类当中是无法具体形容一个对象的,在抽象类的中的方法也是没有方法体的,也就是说抽象方法可以没有具体的实现。但是前提是这个类必须要是抽象类,用abstract去修饰。
既然可以没有方法体,抽象方法中可以有构造方法吗?
因为在抽象类当中是可以存在属性的,进而肯定是可以存在构造方法的。构造方法存在的意义就是为了帮助属性进行初始化。其执行的顺序也是先执行父类的构造方法再执行子类的构造方法(这里涵盖抽象类的继承我们下一个小节会说明)
/**
* @author Jason
* @date 2023/1/14 21:15
*/
abstract class Aniaml{
public String name;
public Aniaml(String name) {
this.name = name;
System.out.println("这是父类的构造方法");
}
public abstract void func();//存在于抽象类的抽象方法可以没有方法体,前提是必须是抽象类以及方法使用abstrac修饰
}
class Dog extends Aniaml{
public Dog() {
super("junjun");//父类中是有参数的,所以这里我们需要给到name的值
System.out.println("这是子类的构造方法");//
}
@Override
public void func() {//这里应该可以理解,因为子类继承了父类,所以必须重写父类的方法
}
}
public class Test2 {
public static void main(String[] args) {
Aniaml aniaml=new Dog();//通过直接赋值的方式实现向上转型
}
}
运行结果:
同样在抽象类当中也是可以包含静态staic修饰的方法
abstract class A{
public static void func(){
System.out.println("func()是存在与抽象类中的静态方法");
}
}
public class Test3 {
public static void main(String[] args) {
A.func();
}
}
运行结果:静态方法可以直接通过类名调用
3.抽象类的继承
大致摸清楚抽象类的概念之后,我们似乎都有一个疑问,在介绍抽象类时,我们通过代码调试发现无法进行实例化,但是一个类存在必须要被实例化。那抽象类存在的意义到底是什么呢?
答案:被继承
当普通继承了抽象类
/**
* @author Jason
* @date 2023/1/14 22:07
*/
abstract class Animal{
public String name;
abstract public void breath();
public Animal(String name) {
this.name = name;
}
}
class Shark extends Animal{
public Shark(String name) {
super(name);
}
@Override
public void breath() {
System.out.println(name+"使用鳃呼吸的");
}
}
class Tiger extends Animal{
public Tiger(String name) {
super(name);
}
@Override
public void breath() {
System.out.println(name+"使用嘴呼吸的");
}
}
public class Test4 {
public static void drawBreath(Animal animal){
animal.breath();
}
public static void main(String[] args) {
// Animal animal1=new Shark("鲨鱼🦈");
// Animal animal2=new Tiger("老虎🐯");
// drawBreath(animal1);
// drawBreath(animal2);
drawBreath(new Shark("🦈鲨鱼"));
System.out.println("================");
drawBreath(new Tiger("🐯老虎"));
}
}
运行结果:
有趣的事情要来了,我是一个普通类,抽象类有抽象方法,我就不去重写你的抽象方法,你咬我啊?
报错出来一瞬间你就明白一个道理,当一个普通类去继承抽象类时,必须要重写父类的抽象方法
当然翻译界面也提到了,解决这个问题还有另外一种方法,就是将子类改成用abstract修饰,就暂时不会有报错出现。⬇️
虽然没有出现报错,但是在这里告诫各位,躲的了初一躲不了15,现在不重写抽象类的抽象方法,下次再出现这样的问题,你就必须要重写,编译器只能帮助你解决一部分的问题,在设计思想中,投机取巧的方式是不可取的 。
4.抽象方法修饰注意点
在我们多态的章节中提到过关于中提到过重写的注意点
大家联想一下,抽象类存在的意义是不是被继承,继承里面又存在重写方法,那么这样一来就理解的通顺了。关于重写的方法在这片文章可以查阅,链接: 重写补充
- 用private去修饰抽象类方法
当用private去修饰抽象方法时,代表这个方法只能在当前对象中使用,无法再被继承,我们抽象类存在意义时冲突的
- 用static修饰抽象方法
还记得static的语法吗,static不依赖于对象,可以通过类来调用。 当抽象方法被static修饰,肯定也是报错状态
- 用final去修饰抽象方法
我们在继承章节也说道过,final关键字可以用来修饰变量,方法,以及类,一旦被final修饰就变成了常量,常量是无法再去更改的。
补充抽象类不能被实例化
虽然我们不能对抽象类进行实例化。
但是我们可以对其子类进行实例化,利用直接赋值,达到向上转型的效果即可。
总结
抽象类特性总结
- 抽象类通过abstract来修饰,内部可以包含成员属性,构造方法,普通方法。
- 抽象类无法被实例化,但是可以通过对子类进行向上转型。
- 抽象类当中可以包含抽象和非抽象方法。
- 什么是抽象方法,一个方法被abstract修饰,没有具体的实现(没有方法体),一旦包含抽象方法,这个类必须是抽象类,或者类名用abstrcact修饰
- 当一个普通类继承了抽象类,这个类必须重写抽象类中的抽象方法
- 抽象类存在的意义就是被继承
- 抽象方法是不能被priavte、final、static修饰的,和重写方法的规则相同
- 抽象类必须有子类,使用extends继承,一个子类只能继承一个抽象类。