1.🍤 抽象类
本篇博客主要给大家介绍关于抽象类的一些概念和性质 建议收藏食用哦
一图流👇
看完这些知识点,相比你肯定有一些疑惑了,没关系,带着疑惑往下阅读,事半功倍哦
1.1🧋 抽象类概念
在面对对象得概念中,所有得对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的
如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类我们就可以称之为抽象类。
比如:👇
又比如:👇
在打印图形的例子中,我们发现了,父类Shape中的draw方法好像并没有什么实际的工作,主要的绘制图形都是由Shape的各种子类(比如矩形类,三角形类,圆类)中的draw方法来完成的。
像这种没有实际工作的方法,我们就可以把它设计成为一个抽象方法(abstract method),包含抽象方法的类我们称之为抽象类(abstract class)
1.2🍣 抽象类语法
在Java中,一个类如果被abstract修饰成为抽象类,那么抽象类中被abstract修饰的方法就称为抽象方法,抽象方法中不用给出具体实现的语句,例如:👇
//抽象类
public abstract class Shape{
//抽象方法:被abstract修饰的方法,没有方法体
abstract public void draw();
abstract void calcArea();
//抽象类也是类,也可以增加普通方法和属性
public double getArea(){
return area;
}
protected double area;//面积
}
注意:抽象类也是类,内部可以包含普通方法和属性,甚至构造方法
1.3🦪 抽象类特性
- 🍜 抽象类不能直接实例化对象
Shape shape = new Shape();
//编译出错
如果一定要实例化,那么我们可以重写其中的方法,让它变得可以运行
这里先埋个伏笔以后再专门来讲
- 🍜抽象方法不能用private来修饰 ```java abstract class Shape { abstract private void draw(); }
//编译出错 Error:非法的修饰符组合:abstract和private
![image.png](https://cdn.nlark.com/yuque/0/2022/png/25529268/1649671972580-10135970-8d9e-4fbe-9fd9-16654004da2d.png#clientId=u40b60633-2002-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=255&id=ude5bf250&margin=%5Bobject%20Object%5D&name=image.png&originHeight=319&originWidth=700&originalType=binary&ratio=1&rotation=0&showTitle=false&size=44056&status=done&style=none&taskId=u20a66720-edf4-4e59-8bf2-64c3d581917&title=&width=560)<br />**注意:抽象方法没有加访问限定符,默认是public**
3. **🍜 抽象方法不能被final和static修饰,因为抽象方法需要被子类重写**
```java
public abstract class Shape {
abstract final void methodA();
abstract public static void methodB();
}
编译报错:👇
🍜 抽象类必须被继承,并且继承之后子类要重写父类中的抽象方法,除非子类也是抽象类,否则就必须要使用abstract修饰 ```java //矩形 public class Rect extends Shape{ private double length; private double width;
Rect(double length,double width){
this.length = length;
this.width = width;
}
@Override public void draw() {
System.out.println("矩形:length="+length+"width="+width);
}
@Override void calcArea() {
area = length*width;
System.out.println("面积为"+area);
} }
//圆类 public class Circle extends Shape{ private double r; final private static double PI = 3.14; public Circle(double r){ this.r = r; }
@Override
public void draw() {
System.out.println("圆:r ="+r);
}
@Override
void calcArea() {
area = PI*r*r;
System.out.println("面积为"+area);
}
}
//三角形类 public class Triangle extends Shape{ private double a; private double b; private double c;
@Override
public void draw() {
System.out.println("三角形:a="+a+
" b="+b+
" c="+c);
}
@Override
public void calcArea() {
double C = (a + b + c) / 2;//周长的一半
double S = Math.sqrt(C*(C-a)*(C-b)*(C-c));//面积
System.out.println("面积为"+area);
}
// @Override // void calcArea(); // 这里这样写编译会失败,该类抽象方法被继承了之后必须重写 // 或者将三角形类设计为抽象类 }
```
- 🍜 抽象类中不一定包含抽象方法,但是又抽象方法的类一定是抽象类
- 🍜 抽象类中可以有构造方法,供子类创建对象时,初始化父类的成员变量
1.4🍔 抽象类的作用
抽象类本身不能被实例化,想要使用,需要创建该抽象类的子类,然后让子类重写抽象类中的抽象方法那么问题来了,普通的类也可以被继承呀,普通的方法也可以被重写呀,那为什么非要用抽象类和抽象方法来实现捏?
确实时这样,但在这里,使用抽象类就相当于多了一个编译器需要执行的校验(就是多了一道关卡,方便我们找到错误)
使用抽象类的场景就像上面的代码,实际工作不应该由父类来完成,而是应该由子类来完成,那么此时如果我们不小心误用成父类中的性质了,如果这个父类是普通类,那编译器是不会报错的,但如果父类是抽象类的话,实例化的时候就会提示报错,让我们尽快得发现错误
很多语法存在的意义都是为了能够“预防出错”,比如我们使用过的final也是如此。 创建的变量用户不去修改的话不就相当于常量嘛? 但是我们如果加上final就能够在不小心误修改的时候,让编译器及时提醒我们 充分利用好编译器的校验在我们学习编程以及实际开发的过程中是非常有意义的
抽象类内容不多,但一定要和接口做好区分,不能弄混
希望能帮到你
感谢阅读~