概述:在Java中,一个没有方法的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类。
多态分为三种:
- 具体类多态(几乎没有):
class Fu { }
class Zi extends Fu { }Fu f = new Zi();
请看 Java多态实例详解三步走(一)【具体类多态】 - 抽象类多态(常用):
abstract class Fu { }
class Zi extends Fu { }Fu f = new Zi();
- 接口类多态(最常用):
interface class Fu { }
class Zi implements Fu { }Fu f = new Zi();
请看 Java多态实例详解三步走(三)【接口多态】多态中必须对方法进行重写,其实是针对于抽象类来说的。因为父类中虽然是对某一种事或物共同的特点,但是,比如说动物。所有的动物都要吃东西,而大象是用鼻子卷着吃,猴子是用手拿着吃,所以定义的子类就要重写方法,既然要重写那为什么不把父类中的方法抽象呢。
一、抽象类的特点:
1、 抽象类和抽象方法必须用abstract关键字修饰。
2、 抽象类中不一定有抽象方法,但是有抽象方法的类必须定义为抽象类。
3、 抽象类不能实例化。
- 因为它不是具体的
- 抽象类有构造方法,但是不能实例化
- 构造方法的作用是,用于子类访问父类数据的初始化
4、抽象的子类
- 如果不想重写抽象方法,该子类是一个抽象类。
- 重写所有的抽象方法,这个时候子类是一个具体的类。
抽象类的实例化其实是靠具体的子类实现的。是多态的方式。
A a = new B();
代码1:
public class Main {
public static void main(String[] args) {
//抽象类无法创建对象,也就是无法实例化
//AA a = new AA();//这里会报错 Cannot instantiate the type AA
//通过多态调用
A a = new C();
a.eat();//输出 吃饭了
}
}
abstract class AA {}
abstract class A {
//下面这种叫 空方法体,不是抽象方法,所以会报错
//public abstract void eat() {}
//正确格式
public abstract void eat();//如果将这行注释,同样不会报错。因为抽象类不一定有抽象方法
}
//子类是抽象类
abstract class B extends A {}
//子类是具体类,重写全部抽象方法
class C extends A {
public void eat() {
System.out.println("吃饭了");
}
}
二、抽象类的成员特点:
1、成员变量:即可以是变量,也可以是常量。
2、构造方法:有。
- 用于子类访问父类数据的初始化
3、成员方法:既可以是抽象的,也可以是非抽象的。
- 抽象类的成员方法特性:
1、抽象方法:强制要求子类做的事情。
2、非抽象方法:子类继承的事情,提高代码复用性。
代码2:
public class Main {
public static void main(String[] args) {
A a = new B();
System.out.println(a.flag);//输出 19
System.out.println(a.logo);//输出 77
a.show();//输出 重写抽象方法
a.show2();//输出 非抽象方法
}
}
abstract class A {
int flag = 19;
final int logo = 77;
public A() {}
public A(String args) {}
public abstract void show();
public void show2() {
System.out.println("非抽象方法");
}
}
class B extends A {
public void show() {
System.out.println("重写抽象方法");
}
}
抽象类中的小问题:
- abstract不能和一些关键字共存
- private 发生冲突
- final 发生冲突
- static 无意义
abstract class Fu{
//私有的不能被重写,而多态中要求被重写
//private abstract void show();
//最终的不能被修改,而多态中要求被重写
//final abstract void show2();
//这里会跟上边两个一样报非法修饰符组合,同时也是无意义的
//static abstract void show3();
//因为,该方法是静态的,我就可以通过类名进行调用 Fu.show3();
//但是因为该方法是抽象方法,没有方法体,所以无意义
}
class Zi extends Fu {
/*public void show(){
System.out.println(123);
}
public void show2() {
System.out.println(528);
}
public void show3() {
System.out.println(520);
}
*/
}
最后用一个代码完整的写出多态
代码3:
public class Main {
public static void main(String[] args) {
Animal a = new Dog();
a.setName("小黄狗");
a.setAge(2);
System.out.println(a.getName());
System.out.println(a.getAge());
a.eat();
System.out.println("------------------");
a = new Cat();
a.setName("小花猫");
a.setAge(6);
System.out.println(a.getName());
System.out.println(a.getAge());
a.eat();
//如果非要访问子类中特有的成员变量或者方法,那就建一个具体的对象
Dog t = new Dog();
t.flag = 90;
System.out.println(t.flag);
}
}
abstract class Animal {
private int age;
private String name;
public Animal() {}
public Animal(int age, String name) {
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
abstract void eat();
}
class Dog extends Animal {
public Dog() {}
public Dog(int age, String name) {
super(age, name);
}
public void eat() {
System.out.println(“狗吃东西”);
}
}
class Cat extends Animal {
public Cat() {}
public Cat(int age, String name) {
super(age, name);
}
public void eat() {
System.out.println(“猫吃东西”);
}
}