抽象类
抽象类是代码开发中重要的组成部分,利用抽象类可以明确的定义子类需要覆写的方法。
1. 抽象类的定义
普通类可以直接产生实例化对象,并且在普通类中可以包含构造方法、普通方法、static方法、常量、变量的内容。
而抽象类就是指在普通类的构造里增加抽象方法的组成部分,抽象方法值得是没有方法体的方法,同时抽象方法还必须使用关键字abstract关键字进行定义。
有抽象方法的类一定属于抽象类,抽象类要使用abstract声明。
一定要记住:抽象类只是比普通类多了抽象方法的定义,其他结构与普通类完全一样。
注意: 抽象类不能直接实例化对象。
如果想使用抽象类,必须遵守如下规则:
|- 抽象类必须有子类,即每一个抽象类一定要被子类继承(单继承)。
|-抽象类的子类(子类不是抽象类)必须覆写抽象类中的全部抽象方法(强制子类覆写)。
|- 依靠对象的向上转型概念,可以通过抽象类的子类完成抽象类的实例化对象操作。
在实际的开发中,是继承一个普通类还是抽象类?
回答:虽然一个子类可以去继承任意一个普通类,但是从开发的实际要求来讲,普通类不要去继承另外一个普通类,而要继承抽象类。
2. 抽象类的相关限制
|- 抽象类里面由于会存在一些属性,那么在抽象类中一定会存在构造方法,目的是为属性初始化。并且子类对象实例化时依然满足先执行父类构造再调用子类构造的情况。
|- 抽象类不能使用final定义,因为抽象类必须有子类。
|- 抽象类中可以没有任何的抽象方法,但是只要时抽象类,就不能直接用new实例化对象。
|- 抽象类中依然可以定义内部的抽象类,而实现的子类也可以根据需要选择是否定义内部类来继承抽象内部类。
|- 外部抽象类不允许使用static声明,而内部的抽象类允许使用static声明,使用static声明的抽象类就相当于是一个外部抽象类,继承的时候使用“外部类.内部类”的形式表示类的名称。
技术拓展:
利用static可以在抽象类中定义不受实例化对象限制的方法。例如,现在抽象类只需要一个特定的系统子类操作,那么就可以通过内部类的方式来定义抽象类的子类。
这样的设计在系统类库中会比较常见,目的是为用户隐藏不需要知道的子类。
对于之前问题的总结
之前遗留过一个问题“在任何一个类的构造执行完前,所有属性的内容都是其对应数据类型的默认值”
执行结果为:
- 抽象类应用-----模板设计模式
抽象类的主要特点相当于制约了子类必须覆写的方法,同时抽象类中也可以定义普通方法,而且最为关键的是,这些普通方法定义在抽象类时,可以直接调用类中定义的抽象方法,但是具体的抽象方法内容就必须由子类来提供。
import org.omg.Messaging.SYNC_WITH_TRANSPORT;
abstract class Action{
public static final int EAT = 1;
public static final int SLEEP = 5;
public static final int WORK = 7;
public abstract void eat(); //定义了三个抽象方法
public abstract void sleep();
public abstract void work();
public void command(int flag){ //普通方法
switch (flag){
case EAT:
this.eat();
break;
case SLEEP:
this.sleep();
break;
case WORK:
this.work();
break;
}
}
}
class Robot extends Action{
public void eat(){
System.out.println("机器人补充能量!");
}
public void sleep(){ // 此方法不需要但必须覆写
}
public void work(){
System.out.println("机器人正在为您打扫卫生!");
}
}
class Huamn extends Action{
public void eat(){
System.out.println("人类正在吃饭!");
}
public void sleep(){
System.out.println("人类正在睡觉休息!");
}
public void work(){
System.out.println("人为了梦想正在努力工作!");
}
}
class Pig extends Action{
public void eat(){
System.out.println("猪正在啃食槽!");
}
public void sleep(){
System.out.println("猪正在睡觉养膘!");
}
public void work(){ //此方法不需要但是必须覆写
}
}
public class Test {
public static void main(String args[]){
fun(new Robot());
fun(new Huamn());
fun(new Pig());
}
public static void fun(Action act){ //传参处是一个向上转型
act.command(Action.EAT);
act.command(Action.SLEEP);
act.command(Action.WORK);
}
}
以上程序中的fun()方法实现了固定的行为操作,并且这些具体的行为都是根据传递的子类的不同而有所不同。这些不同的类型最终都在行为上成功的进行了抽象,即如果要使用行为操作,就必须按照Action类的标准来实现子类。