JavaSE基础(九)——抽象类与接口
前言
本篇笔记记录抽象类和接口以及相关区别,其实抽象类与接口都基于抽象思维,大家可以基于抽象思想理解抽象类与接口的作用。
抽象类简述
被abstract修饰的类就是抽象类,抽象类的目的和意义就是抽象思想的具现化。抽象类中通过声明或定义抽象方法来给该类更大的可能。
之前我们说过,类就是对一个客观存在的宏观描述,这本身就是一个抽象思维的体现。但是我们发现对有些存在分类的时候出现了一个极为庞大的概念,其中包含的种类繁多,操作起来十分不便,所以我们就有了抽象类——通过分层设定条件的分类方式对其进行树型分类,这种分类方式其实体现在生活中的点点滴滴,比如:书的目录、编程语言分类以及最具代表性的古籍——《本草纲目》。
抽象类是基于抽象思维的,但是具体实现是依靠继承(也可以反过来说,抽象解决普通类之间继承所无法完成的工作)。
抽象类无法实例化对象,因为抽象类可以简单理解为比类更抽象的描述,无法明确的提供可以定性的宏观描述的特征,即没有足够的信息给实例化操作进行描述,生成客观的存在。
再次重申,对象是客观存在的。科学猜想等假设等可以理解为:该存在是假设客观存在,即我们认定它必然存在,才可以继续研究。所以只有明确合理的客观存在的才可以被抽象除特征。
在抽象类中,被abstract修饰的方法称为抽象方法,在继承抽象类的子类中可以重写该抽象方法,在使用方面和普通类继承并没有太大的区别。首先来看一下抽象类定义和抽象方法的声明和定义:
public abstract class A{
public abstract void show(){
}
}
看到这里可能会与你们对于抽象类认知有些不同,我会对抽象类进行系统的解释。
抽象类特性
在上述代码中我们使用abstract关键字修饰,使其成为抽象类或者抽象方法。其实使用他们也会是继承而已,只是与普通类使用上略有不同,具体如下:
- 抽象类可以定义常量以及普通方法,抽象方法可有可无;
- 抽象类无法自己实例化对象,需要靠子类实例化,可以采取向上转型的方式来操作抽象类中的方法(抽象类中必须有构造器);
- 抽象类中可以定义普通方法,但是抽象方法不能有方法体;
public abstract class Person{
public void show(){
}
public abstract void action();
// default abstract void a();
// private abstract void b();
}
- 上面代码中注释的两条表示,抽象类无法使用default以及private修饰(抽象方法是被继承的,这两种修饰符会阻碍方法继承);
- 抽象类必须被子类继承,而且继承后必须重写父类抽象方法,否则子类也应该修饰为抽象类;
- 抽象类不能被final修饰;
- 抽象类可以继承抽象类;
- 在原则上,不建议普通子类继承普通子类,建议子类继承抽象类;
- 抽象类中的普通方法默认修饰符:
- Java8以前,protected;
- Java8时,default。
- 抽象类比较具有特色的实现是GOF23种设计模式中的工厂方法。
接口简述
首先说明,我们创建普通类和抽象类的时候,类名的前面都会有一个class,这表示声明类文件;而接口的声明关键字interface。这代表我们之前学的包括抽象类都是类文件体系,接口和类的体系不太相同,所以在某些规则中和普通类不大一样。
public interface A{
public void show();
void action();
}
接口也是基于抽象思维,具体特性如下:
-
Java1.8前:
- 抽象中的方法修饰符默认为public abstract,且必须为public abstract;
- 接口中只能有方法声明,不能有方法体;
- 接口 里只能有静态常量,且必须被final修饰符修饰;
- 不能有构造方法;
- 不能继承类;
- 接口无法实例化对象,只能通过实现类来实例化对象,可以通过向上转向来使用;
- 接口必须有实现类,且实现类不为抽象类的时候必须重写接口中声明的所有方法;
- 实现接口使用implements,且接口可以多实现,即子类可以实现多个接口;
- 接口同样不能使用final关键字修饰。
-
Java1.8:记录与Java1.8以前不同的点
- 接口中的方法默认为public abstract,但是可以设定为default abstract;
- 接口中的方法可以有方法体,且修饰符必须为default abstract;
- 接口可以另类的实例化,使用 getInstance() 方法来获取接口的实例化;
- 如果某个接口实现了两个接口,且两个接口中有同名方法,则必须重写方法,否则会报错;
- 接口可以定义静态方法,和类的规则差不多,只能通过接口名.静态方法来操作,子类和实现类无法调用;
以上是接口的相关概念以及不同之处,现在高校中所讲解的接口多数都是Java1.8以前的规范,很少有讲Java1.8开始的规范。
接口在Java1.8中的一个巨大的变化就是可以定义方法体,其目的是在某些老系统中,我们对于接口种方法的声明可能不太适合现在的需求,如果因为增加功能而在接口中增加方法声明的话会使得系统中实现该接口类都需要更改(子类必须重写接口全部方法),接口新特性提出后便可以解决很多功能需求方面的问题。比如:Lambda表达式在Java1.8中的实现就归功于接口的新特性。(Lambda表达式是什么后续会有讲解)。
总结
接口可以理解为一种规范,一种凌驾于抽象类的规范;个人认为接口是Java中最接近抽象思想本源的存在,他可以仅仅定义一些客观存在的最基本的特征,比如:定义地球上所有的生物都有细胞、都是碳基生物。所以在编程的时候如果需要定义接口,那么一定要多加思考,接口定义的好坏从某种程度上可以影响你程序的开发进度甚至是成败。
抽象类和接口都是在实践中会有效果,在此仅仅介绍思想以及相关特性,具体如何使用大家可以去学习GOF23种设计模式来了解抽象思想以及抽象类、接口。