紫薇星上的Java——抽象类与模板设计模式

前几天我们整理了继承,继承中提到过抽象类,今天我们就来说一下抽象类以及利用抽象类可以做哪些事。


类继承的主要作用在于扩充已有类的功能,但是在对于之前的继承操作而言会发现,子类可以任意决定是否要覆写一个方法,此时父类不能强制对子类进行约定,即强制性子类必须覆写某些方法;这时候我们很少进行对某个类的继承,或者说在开发中,我们很少继承一个已经完善功能的类,这时候我们就要进行继承抽象类。

1.抽象类基本概念

抽象类主要作用为对之类中覆写方法进行约定,在抽象类中可以去定义一些抽象方法以实现这样的约定,抽象方法指的是使用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;
	}
}

于是我们试着new一个Message对象:

public class first {
	public static void main( String args[] ){
		Message msg = new Message();
		System.out.println(msg.getConnectInfo());
	}
}

结果发现出错了:

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
	Cannot instantiate the type Message

我们要知道,当一个抽象类定义完成之后,它不是完整的,要想使用抽象类,必须依据下列几点:

  1. 抽象类必须提供子类,子类使用extends继承一个抽象类
  2. 抽象类的子类一定不是抽象类,在不是抽象类的前提下,要覆写抽象类的全部抽象方法
  3. 抽象类的对象实例化可以利用对象多态性通过子类向上转型的方式来完成

在刚才的例子中,我们来实现一下。首先我们添加一个子类来继承Message类:

class DatabaseMessage extends Message{
}

这个时候我们如果直接编译会报错,当然使用工具的同学可能不会发现报错信息,但会有错误提示:

而当我们在子类中覆写抽象方法时,就没有报错了:

class DatabaseMessage extends Message{
	public String getConnectInfo() {
		return "方法覆写";
	}
}

同时,我们来实例化一个对象,看能不能不管成功的向上转型实例化出来:

public class first {
	public static void main( String args[] ){
		Message msg = new DatabaseMessage();
		msg.setType("Type消息");
		System.out.println(msg.getType());
		System.out.println(msg.getConnectInfo());
	}
}

我们想要new一个Messaga对象,来实现他的抽象方法,利用DatabaseMassage类来实现父类中的抽象方法,同时对象本身属于Message类,可以使用类中的普通方法:

public class first {
	public static void main( String args[] ){
		Message msg = new DatabaseMessage();
		msg.setType("Type消息");
		System.out.println(msg.getType());
		System.out.println(msg.getConnectInfo());
	}
}

上述代码编译后运行结果为:

Type消息
方法覆写

从整体上来说,抽象类只是比普通类增加了抽象方法以及对子类的强制性覆写要求,其他使用过程和传统的类继承是完全相同的。对于抽象类使用的几点意见:

  1. 抽象类使用很大程度上因为抽象类无法直接实例化。
  2. 抽象类之中主要目的是进行过渡操作使用,所以当你使用抽象类开发的时候,往往都是在设计中需要解决类继承时所带来的代码重复的问题。

2.抽象类的相关说明

抽象类是一个重要的面向对象的设计结构,对于抽象类使用的时候要注意以下几点:

  1. 在定义抽象类的时候不能使用final关键字来定义,因为抽象类必须要有子类,但是final关键字不能有子类。
  2. 抽象类是作为一个普通类的加强版出现的(抽象类的组成就是在普通类的基础上扩展而来的,只是追加了抽象方法),那么普通类之中可以定义属性和方法,而抽象类基于普通类也就可以提供构造方法,并且子类也一定会按照子类对象的实例化原则进行父类构造调用。

我们首先在Message中添加一段代码,这段代码用来定义一个构造方法:

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;
	}
}

然后我们运行程序,结果如下:

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
	Implicit super constructor Message() is undefined for default constructor. Must define an explicit constructor

这时候我们需要在子类中添加一段代码,由于父类的构造方法没有无参构造,所以子类必须明确的调用无参构造:

class DatabaseMessage extends Message{
	public DatabaseMessage(String str) {//添加的代码
		super(str);
	}
	public String getConnectInfo() {
		return "方法覆写";
	}
}

这时候我们就可以直接在实例化的时候传递参数了:

public class first {
	public static void main( String args[] ){
		Message msg = new DatabaseMessage("Type消息");
		System.out.println(msg.getType());
		System.out.println(msg.getConnectInfo());
	}
}

因为我们通过DatabaseMessage类实例化了一个Message类的对象,而传递过去的参数str就到了父类的构造方法中,这样就能显示出来了,运行上述代码,结果如下:

Type消息
方法覆写

我们还要注意:

  1. 抽象类中允许没有抽象方法,但是即便没有抽象方法也不能直接通过new关键字来实例化对象,要获取对象只能通过子类。
  2. 抽象类中可以提供有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 first {
	public static void main( String args[] ){
		Message msg = Message.getInstance();
		System.out.println(msg.getInfo());
	}
}

我们在Message类中定义一个抽象方法,在DatabaseMessage类中覆写它,然后再定义一个static关键字的方法getInfo(),用来实例化DatabaseMessage类的对象,那么编译之后运行结果为:

方法覆写

所以我们就可以知道,static方法永远不受结构的影响,永远都可以使用类名称调用。

3.模板设计模式

抽象来本质上就属于一个加强型的类,对于类已经很清楚了,可以描述一切有关的现实事物,但是通过分析可以发现,抽象类的定义应该是比我们普通的类更高一级的定义。对于抽象类的实际应用来研究一下:

假如说我们现在要描述有三类事物:

  • 机器人:不休息,补充能量和工作
  • 人类:需要休息,吃饭和努力的工作
  • 猪:天天休息,吃饭,不需要工作

如果我们要实现描述这三类事物,首先要明确这三类事物的形为都是一致的:吃、睡、工作,所以我们首先定义一个抽象类,再通过子类将行为具体实现:

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 :{
				this.eat();
				this.sleep();
				break;
			}
			case EAT + WORK :{
				this.eat();
				this.work();
				break;
			}
			case SLEEP + WORK :{
				this.sleep();
				this.work();
				break;
			}
			case EAT + SLEEP + WORK :{
				this.eat();
				this.sleep();
				this.work();
				break;
			}
		}
	}
	public abstract void eat();
	public abstract void sleep();
	public abstract void work();
}

在上面这段代码中,我们首先定义了一个抽象类,以及所有的抽象方法;同时为了避免识别错误,我们分别用1、5、10来代替吃饭、睡觉、工作,这样我们就可以开始编写子类了:

class Robot extends Action{
	public void eat() {
		System.out.println("充电来补充能量!");
	}

	public void sleep() {
		System.out.println("不需要休息!");
	}

	public void work() {
		System.out.println("严谨有序的工作!");
	}
}

class Reson 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() {
		System.out.println("不需要工作!");
	}
}

这三个子类分别对应了机器人、人类、猪的行为,需要注意的是,如果没有动作,那么方法中可以不写任何内容,例如机器人不需要休息,那我们将Robot类中的sleep()方法空着也是完全没有问题的!

接下来我们来实例化三个对象并根据不同的子类产生不同的行为:

public class first {
	public static void main( String args[] ){
		Action robotact = new Robot();
		Action resonact = new Reson();
		Action pigact = new Pig();
		System.out.println("**********机器人行为**********");
		robotact.command(Action.EAT + Action.SLEEP + Action.WORK);
		System.out.println("**********人类行为**********");
		resonact.command(Action.EAT + Action.WORK);
		System.out.println("**********猪的行为**********");
		pigact.command(Action.SLEEP);
	}
}

可以看到我们展示了三种不同的行为状态:

**********机器人行为**********
充电来补充能量!
不需要休息!
严谨有序的工作!
**********人类行为**********
吃饭来补充能量!
努力的工作!
**********猪的行为**********
经常在休息!

这样就可以看到所有的对象的行为了;当然,如果在子类中自己写一个新的方法来实现吃、睡、工作等行为,由于父类并不知道有这样的方法存在,所以传递参数给父类就没有任何反馈。

抽象类的好处:

  1. 对子类方法的统一管理。
  2. 自身可以提供一些普通方法,并且可以调用抽象方法(这些抽象方法必须在有子类提供实现的时候才会生效)。

这就是一种模板设计的模式,要想实现某些功能,就按照父类要求写方法,父类就会按照标准调用,如果不规范写方法,那父类就会报错。


这篇文章整理了抽象类以及抽象类可以实现的模板设计模式,这是一种非常规范的,实用的设计模式,虽然在实际开发中规范书写代码比较困难,但大家还是要掌握,我们下次见👋

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 易排盘.紫微斗数v3.0是一款专业的紫微斗数软件。它结合了易学和星法两种传统的中国文化,并利用先进的计算机技术,提供了准确的命盘排算和预测功能。 易排盘.紫微斗数v3.0的主要功能包括命盘排盘、命宫分析、宫位解读、十二宫运势、星座配对等。通过输入个人的出生日期、时间和地点,软件可以准确计算出个人的命盘,并提供详细的解读和预测。 命宫分析是易排盘.紫微斗数v3.0的重要功能之一。通过分析命宫的星位、星君和星座等信息,软件可以揭示个人的性格特点、运势走向和吉凶指数。它可以帮助人们更好地了解自己的优点和不足,并为未来的发展提供一些建议和方向。 宫位解读是易排盘.紫微斗数v3.0的另一个关键功能。它通过分析各个宫位的星座和星位,帮助人们了解自己在事业、爱情、财运和健康等方面的潜力和可能性。宫位解读可以为人们选择适合自己的发展方向和战略提供重要参考。 十二宫运势是易排盘.紫微斗数v3.0的预测功能之一。通过分析时空的变化和个人命盘的关系,软件可以预测每个人在不同时期的运势走向和吉凶指数。十二宫运势可以帮助人们更好地把握时机、规划未来,以求顺利和成功。 总之,易排盘.紫微斗数v3.0是一款功能强大的紫微斗数软件。它不仅可以帮助人们了解自己的命运和潜力,还可以为个人的发展和决策提供重要参考。无论是对于易学爱好者还是寻求个人发展的人来说,这是一款非常实用和有价值的工具。 ### 回答2: 易排盘是一款专业的紫微斗数软件,它的版本号是v3.0。紫微斗数是一种古老的中国命理学术,通过排盘来分析一个人的命运和命理特点。 易排盘.紫微斗数v3.0具有多种功能和特点。首先,它提供了准确的星盘计算功能,可以根据出生时间、日期和地点准确排盘,得到一个人的生辰八字和命宫。 其次,它提供了多种分析工具,可以根据紫微斗数的理论,分析一个人的八字命盘,解读其中的吉凶祸福,预测一个人的命运走势。 此外,易排盘.紫微斗数v3.0还提供了丰富的学习资料和案例分析,帮助用户更好地了解紫微斗数的基本原理和应用方法。 另外,易排盘.紫微斗数v3.0还提供了个性化的设置功能,用户可以根据自己的需求进行设置,例如选择特定的历法和计算方式等。 总的来说,易排盘.紫微斗数v3.0是一款功能强大、专业准确的紫微斗数软件,它通过准确的星盘计算和丰富的分析工具,帮助用户深入研究命理学术,解读命运,做出更好的决策。具体来说,用户可以通过它来了解自己的八字命盘,预测个人运势,以及选择合适的发展方向。 ### 回答3: 易排盘.紫微斗数v3.0是一款专业的紫微斗数软件,主要用于命理推断和占卜。它结合了易经和紫微斗数理论,并借助计算机算法,提供准确、快速的命运分析和预测。 该软件首先需要用户提供出生日期、出生地点和出生时间等信息,然后根据紫微斗数的理论将这些信息转化为对应的命盘图。命盘图由十二宫位和星宿组成,每个宫位代表不同的人生领域,而星曜则代表个人的命运和特质。 软件会根据用户的命盘图分析个人的性格特点、事业发展、财富状况、婚姻情况、健康状况等方面的信息。通过分析十二宫位和星曜的位置和相互关系,软件能够准确预测用户的人生走势和重要事件,并给出相应的建议和指导。 这个软件的优势在于它的准确性和全面性。它使用复杂的算法和紫微斗数的理论,能够在短时间内为用户做出系统全面的命运分析。它的计算速度快,准确性高,不会受到人的主观意识和偏见影响。 此外,易排盘.紫微斗数v3.0还提供了易经占卜的功能。用户可以根据自己的问题,输入相关信息,软件会根据易经的原理和卦象的图像,为用户提供具体的占卜结果和解答。 总之,易排盘.紫微斗数v3.0是一款功能强大、准确可靠的紫微斗数软件。它能够帮助用户了解自己的命运走势,为个人的发展提供指导和建议。无论是对于命理学研究者还是对于对自己命运感兴趣的人来说,这是一款值得拥有的优秀软件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值