举个例子来说:
class Animal{
String name;
String color;
public Animal(String name,String color){
this.name=name;
this.color=color;
}
public void run(){
System.out.println(name+"四条腿跑的很快");
}
}
class Dog extends Animal{
public Dog(String name,String color){
super(name,color);
}
}
class Fish extends Animal{
public Fish(String name,String color){
super(name,color);
}
}
public class Abstract {
public static void main(String[] args) {
Dog d=new Dog("牧羊犬","白色");
d.run();
Fish f=new Fish("金鱼","金黄色");
f.run();
}
}
运行结果我们发现,动物行动方法不符合动物,但是当我们运行的时候,发现了错误,已经晚了,我们要在运行以前告诉他重写动物行动方法。
我们会发现,所有的动物都是行动的方法都是不一样的!
目前存在的问题
1. 没有强制通知子类一定要重写run方法
2. 动物类的run方法描述不正确
抽象类的应用场景
解决方法:我们在描述一类事物的时候,发现这种事物确实存在着某种行为,但
是这种行为目前是不具体的,那么我们可以抽取这种行为的声明,但是不去实现
该种行为,这时候这种行为我们称作为抽象的行为,我们就需要抽象类来解决这
个问题。
正确的做法:
abstract class Animal{
String name;
String color;
public Animal(String name,String color){
this.name=name;
this.color=color;
}
public abstract void run();
}
class Dog extends Animal{
public Dog(String name,String color){
super(name,color);
}
public void run(){
System.out.println(name+"四条腿跑了很快");
}
}
class Fish extends Animal{
public Fish(String name,String color){
super(name,color);
}
public void run(){
System.out.println(name+"在水中游的很快");
}
}
public class Abstract {
public static void main(String[] args) {
Dog d=new Dog("牧羊犬","白色");
d.run();
Fish f=new Fish("金鱼","金黄色");
f.run();
}
}
- 抽象类要注意的细节:
- 如果一个函数没有方法体,那么该函数必须要使用abstract修饰,把该函数 修饰成抽象的函数
- 如果一个类出现了抽象的函数,那么该类也必须使用abstract修饰
- 如果一个非抽象类继承了抽象类,那么必须要把抽象类的所有抽象方法全部实现
- 抽象类可以存在非抽象方法,也可以存在抽象的方法。
- 抽象类可以不存在抽象方法的。虽然语法是支持的,但是我们一般不会去这样使用,抽象类肯 定会使用抽象方法,这时候我们才使用抽象类的,否则我们就使用普通的类了。
- 抽象类是不能创建对象的。
- 抽象类是存在构造函数的,因为构造函数是提供给子类创建对象的时候初始化父类属性的。
疑问:为什么抽象类不能创建对象呢?
因为抽象类是存在抽象方法的,如果能让抽象类创建对象的话,那么使用抽象的对象
调用抽象方法时没有任何意义的。
抽象类的练习:
需求:描述一个图形类,圆形类,矩形类三个类。不管哪种图形,都会具备计算面积与周长的行为,但是每种图形计算单方法不一致。
abstract class MyShape{ //图形类
String name;
public MyShape(String name){
this.name=name;
}
public abstract void getArea();
public abstract void getLength();
}
//圆形是属于图形类的一种
class Circle extends MyShape{
double r;
public static final double PI=3.14;
public Circle(String name,double r){
super(name);
this.r=r;
}
public void getArea(){
System.out.println(name+"的面积是:"+PI*r*r);
}
public void getLength(){
System.out.println(name+"的周长是"+2*PI*r);
}
}
//矩形
class Rect extends MyShape{
int width;
int height;
public Rect(String name,int width,int height){
super(name);
this.width=width;
this.height=height;
}
public void getArea(){
System.out.println(name+"的面积是:"+width*height);
}
public void getLength(){
System.out.println(name+"的周长是"+2*(width+height));
}
}
public class Abstractlianxi {
public static void main(String[] args) {
Circle c=new Circle("我是园",4.0);
c.getArea();
c.getLength();
Rect r=new Rect("我是矩形",5,3);
r.getArea();
r.getLength();
}
}
常亮的命名规范:全部字母大写,单词与单词之间使用下划线分割。
abstract不能与以下关键字共同修饰一个方法:
- abstract不能与private共同修饰一个方法。//private为不可见的
- abstract不能与static共同修饰一个方法。//如果用static修饰,别人就可以使用类名访问了
- abstract不能与final共同修饰一个方法。//final不允许重写