从某种角度看,祖先类更具有通用性,我们只将它作为派生其他类的基类,而不作为想实现特定的实例类。
有的时候,许多子类都需方法,但是,超类并不使用这个方法,这些子类都要自身重写这个方法,这时候超类中只需要声明有这种方法,没有必要有具体的执行语句。这种情况下,可以使用关键字abstract在超类中声明这个函数,这个函数在超类中只有声明,没有定义,除了方法名和空的参数列表之外没有任何东西。包含一个或多个抽象方法的类本身就必须声明为抽象类
注意:抽象类不能使用new来实例化对象。
超类中的抽象方法一定要在子类中得到实现定义,否则子类中会报错。
但是有种情况下是一种特殊情况能new 出实例来。
public abstract class Abstrect {
public abstract void echo();
//public abstract void echo1();
}
public class Text {
public static void main(String[] args) {
Abstrect aa = new Abstrect() {
public void echo() {
System.out.println("new/new/new");
}
};
aa.echo();
}
}
这种情况在程序中是极少出现的,因为实例化的时候连带着将抽象类中的抽象方法也要定义了,如果抽象类中有多个抽象方法,那么我实例一个抽象类的对象要用几十行代码甚至上百行,这种情况是不希望出现的。在这里注意一点,如果抽象类中有空的非抽象的方法可以不在实例化的时候定义,例如代码中的echo1()如果不是抽象的,在测试的类中不会报错。
需要注意的是,可以定义一个抽象类的对象变量,但是它只能引用非抽象类的对象。
public abstract class Abstrect {
private String name;
private int age;
public abstract void echo();
public void echo1() {
}
public Abstrect(String name ,int age) {
this.name = name;
this.age = age;
}
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;
}
}
public class AbstractChild extends Abstrect{
public AbstractChild(String name, int age) {
super(name, age);
// TODO Auto-generated constructor stub
}
@Override
public void echo() {
System.out.println("AbstrectChild 类");
}
}
public class Text {
public static void main(String[] args) {
Abstrect aa = new AbstractChild("heheh",20);
aa.echo();
}
}
结果:
AbstrectChild 类
由此,我们认识到,抽象类中可以存在抽象方法,也可以包含具体的方法和具体的数据。建议尽量将通用的域和方法放在超类中。抽象方法充当着占位的角色,他们的具体实现在子类中。扩展抽象类的方法有两种,一种是在抽象类中定义部分抽象方法或者不定义抽象方法,这样就必须将子类也标记为抽象类,剩余的抽象方法在子类中定义。另一种是定义全部的抽象方法,这样一来,子类就不是抽象的了。
类中没有抽象方法,也可以将类声明为抽象类,但是一个类中只要有一个抽象方法,这个类就一定是抽象类。
public abstract class Person {
private String name;
public abstract String getDescripition();
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void echo() {
System.out.println("我是Person类的方法");
}
}
public class Employee extends Person {
private double salary;
private LocalDate hireDay;
Employee( String n,double s,int year,int month,int day){
super(n);
salary=s;
hireDay=LocalDate.of(year, month, day);
}
public double getSalary() {
return salary;
}
public LocalDate getHireDay() {
return hireDay;
}
public void raiseSalary( double x) {
double raise = salary*x/100;
salary+=raise;
}
public String change(double sa) {
//return String.valueOf(sa);
return sa+"";
}
public void echo() {
System.out.println("我是员工类型的方法");
}
@Override
public String getDescripition() {
System.out.println("我是员工类的抽象方法");
return change(salary) ;
}
}
public class Student extends Person {
private String major;
public Student(String name,String major) {
super(name);
this.major = major;
}
public void echo() {
System.out.println("我是学生类的方法");
}
@Override
public String getDescripition() {
//System.out.println(name+major);
System.out.println("我是学生类的抽象方法");
return this.major;
}
}
public class Generic {
public static void main(String[] args) {
Person [] people = new Person[2];
people[0] = new Employee("baidu" ,20000,1999,10,19);
people[1] = new Student("taobao" ,"woshitaobao");
for(Person p:people) {
System.out.println(p.getName()+" "+p.getDescripition());
}
}
}
结果:
我是员工类的抽象方法
baidu 20000.0
我是学生类的抽象方法
taobao woshitaobao