目录
一,抽象类
1,什么是抽象类?
2,为什么要有抽象类?
3,抽象类注意事项
二,模板设计模式
抽象类就是抽象的类,所谓的抽象是相对于具体而言的。一般来说,具体类有直接对应的对象,而抽象类没有,它所表达的是抽象概念。如:动物的抽象概念,而熊猫、兔子等则是具体对象。
在Java中,使用abstract关键字来声明抽象类和抽象方法。示例如下:
public abstract class Animal{
public abstract void eat();
}
定义了抽象方法的类必须被声明为抽象类,抽象类可以没有抽象方法。抽象类除了不能实例化对象之外,类的其他功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。
抽象类不能创建对象,要创建对象必须使用它的具体子类。一个普通类在继承抽象类后,必须实现抽象类中定义的所有抽象方法,如下:
public class Panda extends Animal{
public void eat(){
System.out.println("I like to eat bamboo!!!");
}
}
抽象类虽然不能使用new,但可以声明抽象类的变量,然后引用抽象类具体子类的对象,如下所示:
Animal animal = new Panda();
animal.eat();
下面来看一个完整的示例:
import java.util.*;
abstract class Teacher{
private String name;
private int age;
private double salary;
public Teacher(){}
public Teacher(String name, int age, double salary){
this.name = name;
this.age = age;
this.salary = salary;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return this.name;
}
public void setAge(int age){
this.age = age;
}
public int getAge(){
return this.age;
}
public void setSalary(double salary){
this.salary = salary;
}
public double getSalary(){
return this.salary;
}
public void showMessage(){
System.out.println(getName() + "年龄是:" + getAge() + ", 工资是:" + getSalary());
}
}
class JobTitle extends Teacher{
private String level;
public JobTitle(String name, int age, double salary, String level){
super(name, age, salary);
this.level = level;
}
public void setLevel(String level){
this.level = level;
}
public String getLevel(){
return this.level;
}
public void showMessage(){
System.out.println(getName() + "年龄是:" + getAge() + ", 工资是:" + getSalary() + ", 职称是:" + getLevel());
}
}
public class Test{
public static void main(String[] args){
Teacher teacher = new JobTitle("Steven", 40, 12000.0, "高级教师");
teacher.showMessage();
}
}
看了上述代码,有人会觉得抽象方法和抽象类是多余的,可以直接定义一个空的方法体,而具体的内容由子类去实现也是可以的。接下来,我们就来探讨下一个话题:为什么要有抽象类?
(1)避免误用。Java中引入了抽象类和抽象方法,作为一种纠错机制,帮助使用者更好的使用,减少被误用。当使用抽象方法的时候,子类就必须去实现该方法,不容易被忽略。使用抽象类的时候,类的使用者创建对象的时候,就知道要使用的具体子类,而不可能误用不完整的父类。
(2)相对安全。对于空的方法来说,如上述的eat()方法,我们确实觉得可以通过普通父类定义为空的方法体,然后交给子类去实现。但是如果是带有返回值的呢?比如动物的体重,如果是抽象类,可以写成public abstract double weight();如果是普通父类,那么这个方法中就会存在返回值。Public double weight(){return 0.0}。如果是以这种方式交给子类去实现,一旦子类忘记实现,那么会出现问题。而抽象类规定了子类必须实现抽象方法,在一定程度上做了保障。
(1)抽象类不能被实例化,如果被实例化,就会报错,编译无法通过。只有抽象类的非抽象子类可以创建对象。
(2)抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
(3)抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能。
(4)构造方法、类方法(用 static 修饰的方法)不能声明为抽象方法。
(5)抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。
模板设计模式:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。开发人员在开发时,只需要考虑方法的实现。不需要考虑方法在何种情况下被调用。实现代码复用。
优点: (1)封装不变部分,扩展可变部分。 (2)提取公共代码,便于维护。 (3)行为由父类控制,子类实现。
缺点:每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。
使用场景:(1)有多个子类共有的方法,且逻辑相同。 (2)重要的、复杂的方法,可以考虑作为模板方法。
注意事项:为防止恶意操作,一般模板方法都加上 final 关键词。
模拟一个打仗场景,以AbstractClass作为抽象父类,其中定义了一系列操作,声明final不让子类覆盖这个方法,防止改变打仗顺序。
import java.util.*;
abstract class AbstractClass{
public final void process(){
depart();
fight();
triumph();
}
public void depart(){
System.out.println("兵马未动,粮草先行");
}
public abstract void fight();
public void triumph(){
System.out.println("凯旋而归,天下归心");
}
}
class General1 extends AbstractClass{
public void fight(){
System.out.println("借刀杀人,声东击西");
}
}
class General2 extends AbstractClass{
public void fight(){
System.out.println("瞒天过海,以逸待劳");
}
}
public class Test{
public static void main(String[] args){
AbstractClass general1 = new General1();
general1.process();
AbstractClass general2 = new General2();
general2.process();
}
}