抽象类的定义与使用
2020-10-31 本文已影响0人
曾梦想仗剑天涯
- 类继承的主要作用是可以扩充已有类的功能,但是对于之前的继承操作而言会发现子类可以由自己的选择任意来决定是否要覆写某一个方法,这个时候父类无法对子类作出强制性约定(强制性你必须覆写某一个方法),这种情况下往往不会采用类的继承(在实际开发中很少会出现继承一个已经完善的类,可以直接使用的类),而是必须要继承抽象类
- 在以后在进行父类(SuperClass)设计的时候优先考虑的一定是抽象类
抽象类基本定义
- 抽象类的主要作用在于对子类中覆写方法进行约定,在抽象类里面可以定义一下抽象方法以实现这样的约定,抽象方法指的是使用了abstract关键字定义的并且没有提供方法体的方法,而抽象方法所在的类必须是抽象类,抽象类必须使用abstract关键字来进行定义(在普通类的基础上追加抽象方法就是抽象类)。
//定义一个抽象类
abstract class Message { //定义抽象类
private String type;
public abstract String getConnectInfo(); //定义抽象方法
public void setType(String type) { //普通方法
this.type = type;
}
public String getType() { //普通方法
return this.type;
}
}
public class JavaDemo {
public static void main(String [] args) {
//抽象类不可以直接new
//Message msg = new Message();
}
}
- 当一个抽象类定义完成之后(切记:抽象类不是完整的类),如果想去使用抽象类则必须按照如下原则:
- 抽象类必须提供有子类,子类使用extends继承一个抽象类;
- 抽象类的子类(不是抽象类)一定要覆写抽象类中的全部抽象方法;
- 抽象类的对象实例化可以利用对象多态性通过子类向上转型的方式来完成;
//使用抽象类
abstract class Message { //定义抽象类
private String type;
public abstract String getConnectInfo(); //定义抽象方法
public void setType(String type) { //普通方法
this.type = type;
}
public String getType() { //普通方法
return this.type;
}
}
class DataBaseMessage extends Message { //类的继承关系
public String getConnectInfo() { //方法覆写
return "进行了数据连接";
}
}
public class JavaDemo {
public static void main(String [] args) {
Message msg = new DataBaseMessage(); //向上转型
System.out.println(msg.getConnectInfo());
}
}
- 从整体来讲,抽象类只是比普通类增加了抽象方法以及对子类的强制性覆写要求
- 对于抽象类使用的几点意见:
- 抽象类使用很大程度上有一个核心的问题:抽象类自己无法直接实例化;
- 抽象类之中主要目的是进行过渡操作使用,所以当你要使用抽象类进行开发的时候,往往都是在你设计中需要解决类继承问题时所带来的代码重复处理;
抽象类的相关说明
抽象类是一个重要的面向对象设计的结构,对于抽象类使用的时候需要注意几点:
- 在定义抽象类的时候不能用final关键字来定义,因为抽象类必须有子类,而final定义的类是不能有子类的
- 抽象类是作为普通类的加强版出现的(抽象类的组成就是在普通类的基础上扩展而来的,只是追加了抽象方法),既然是在普通类的基础上扩展的,那么抽象类之中就可以定义属性和方法,那么这些属性一定是要求进行内存空间开辟的,所以抽象类一定可以提供构造方法,并且子类也一定会按照子类对象的实例化原则进行构造调用。
- 抽象类之中允许没有抽象方法,但是即便没有抽象方法,也无法直接使用关键字new直接实例化抽象类对象
abstract class Message { //定义抽象类
private String type;
public Message(String type) { //类中没有提供无参构造
this.type = type;
}
public abstract String getConnectInfo(); //定义抽象方法
public void setType(String type) { //普通方法
this.type = type;
}
public String getType() { //普通方法
return this.type;
}
}
class DataBaseMessage extends Message { //类的继承关系
public DataBaseMessage(String str) {
super(str);
}
public String getConnectInfo() { //方法覆写
return "进行了数据连接";
}
}
public class JavaDemo {
public static void main(String [] args) {
Message msg = new DataBaseMessage("客户消息"); //向上转型
System.out.println(msg.getConnectInfo());
System.out.println(msg.getType());
}
}
- 抽象类之中可以提供有static方法,并且该方法不受到抽象类对象的局限
abstract class Message {
public abstract String getInfo();
public static Message getInstance() {
return new DataBaseMessage();
}
}
class DataBaseMessage extends Message {
public String getInfo() {
return "进行了数据连接";
}
}
public class JavaDemo {
public static void main(String [] args) {
Message msg = Message.getInstance();
System.out.println(msg.getInfo());
}
}
抽象类的应用
假如说现在要描述三类事物:
- 机器人:不休息,只需要能量和工作;
- 人:需要休息,需要吃饭和努力的工作;
-
猪:需要休息,不需要工作只需要吃饭;
此图来源于李兴华老师
abstract class Action {
public static final int EAT = 1;
public static final int SLEEP = 5;
public static final int WORK = 10;
public void command(int code) {
switch(code) {
case EAT: {
this.eat();
break;
}
case SLEEP: {
this.sleep();
break;
}
case WORK: {
this.work();
break;
}
case EAT + SLEEP + WORK: {
this.eat();
this.sleep();
this.work();
break;
}
default: {
break;
}
}
}
public abstract void eat();
public abstract void sleep();
public abstract void work();
}
class Robot extends Action {
public void eat() {
System.out.println("机器人补充能量");
}
public void sleep() {};
public void work() {
System.out.println("机器人工作");
};
}
class Person 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 JavaDemo {
public static void main(String [] args) {
Action robotAction = new Robot();
Action personAction = new Person();
Action pigAction = new Pig();
System.out.println("********机器人行为*********");
robotAction.command(Action.EAT);
robotAction.command(Action.WORK);
System.out.println("********人行为*********");
personAction.command(Action.EAT + Action.SLEEP + Action.WORK);
System.out.println("********猪行为*********");
pigAction.command(Action.EAT);
pigAction.command(Action.SLEEP);
}
}
- 定义Action父类主要目的是:对所有行为规范进行统一处理
- 抽象类的好处:一是对子类方法的统一管理,二是可以自身提供一些普通方法,并且这些普通方法可以调用抽象方法(这些抽象方法必须在有子类提供实现的时候才会生效)