抽象类
抽象类的概念
类的设计应该确保父类包含它的子类的共同特征。在继承的层次结构中,每个新的子类都有比父类更加明确和具体的作用。如果一个父类拥有更多个子类可以向父类追溯,父类就应该拥有更通用、同时更加不明确的作用,以满足它众多子类所有的共通性,因为子类越多的父类其共通点或许会越少相较于拥有较少子类的父类。因此,在某些情况下,一个父类会设计的非常抽象,以至于它都没有任何具体的实例,从而允许它能够拥有更多子类能够继承它。这样的类称为抽象类。
抽象类的设计目的,是代码复用。当不同的类具有某些相同或相似的目的要被实现(记为行为集合A),且这些目的的部分达成目标结果的代码(即实现方式)拥有一致时(A的非真子集,记为B),可以让这些类都派生于一个抽象类。在这个抽象类中实现了B,从而使得让所有的子类不用重复大量相同或相似内容的代码来实现B,这就达到了代码复用的目的。而A减B的部分,留给各个子类自己实现。正是因为A-B在这里没有实现,所以抽象类在大多数情况下并不允许被实例化出来(因为能够使其实例化的内容大多会被放在A-B内)。
抽象方法的定义格式:访问修饰符 abstract 返回类型 方法名(参数列表);
例如 public abstract
void getArea();
包含抽象方法的类就是抽象类
必须用abstract
声明
如果子类没有重写父类的抽象方法,编译器会报错
抽象方法会确保子类会实现这个方法
实例
abstract class Zero{//定义一个抽象类
public void fun(){//普通方法
System.out.println("啦啦啦");
}
public abstract void print();//抽象方法,没有方法体,有abstract关键字做修饰
}
//单继承
class B extends Zero{//B类是抽象类的子类,是一个普通类
public void print() {//强制要求重写
System.out.println("JAVA");
System.out.println("521");
}
}
public class zuoye {
public static void main(String[] args) {
Zero a = new B();//向上转型
a.print();//被子类所重写的过的方法
}
}
运行结果:
JAVA
521
- 抽象类继承子类里面有明确的方法重写要求,而普通类可以有选择性的来决定是否需要重写;
- 抽象类实际上就比普通类多了一些抽象方法而已,其他组成部分和普通类完全一样;
- 普通类对象可以直接实例化,但抽象类的对象必须经过向上转型之后才可以得到。
接口类
接口类的概念
- 如果一个类要实现接口,它需要在类头中使用==implements ==关键字
- 一个类只能从一个基类派生
Java 允许一个类实现多个接口
- 当一个类实现多个接口,它必须实现所有接口中的方法
- 接口名之间用逗号分隔
接口是一种与类相似的结构,用于为对象定义共同的操作。接口在许多方面都与抽象类很相似,但是他的目的是指明相关或者不相关类的对象的共同行为。例如,使用适当的接口,可以指明这些对象是可比较的、可食用的或者可克隆的。为了区分接口和类,Java采用下面的语法来定义接口:
modifier interface InterfaceName{
/**Constant declarations*/
/**Abatract method signatures */
}
接口样例
Cloneable接口指定了一个对象可以被克隆
步骤一
创建一个接口
public interface Image{
void display();
}
步骤二
创建实现接口类的实体类
public RealImage implements Image{
public String Filename;
public RealImage(String Filename){
this.Filename = Filename;
loadFromDisk(Filename);
}
@overrride
public void display(){
System.out.println("Displaying " + Filename);
}
private void loadFromDisk(String Filename){
System.out.println("Loading " + Filename);
}
}
public class ProxyImage implements Image{
private RealImage realImage;
private String Filename;
public ProxyImage(String Filename){
this.Filename = Filename;
}
@override
public void display(){
if(realImage == null){
realImage = new RealImage(Filename);
}
realImage.display();
}
}
步骤三
当被请求时ProxyImage来获取RealImage类的对象
public class ProxyPatternDemo{
public static void mian(String[] args){
Image image = new ProxyImage("test_10mb.jpg");
//图像将从磁盘加载
image.display();
system.out.println("");
//图像不需要从磁盘加载
image.display();
}
}
步骤四
输出结果
对于接口,里面的组成只有抽象方法和全局常量,所以很多时候为了书写简单,可以不用写public abstract 或者public static final。并且,接口中的访问权限只有一种:public,即:定义接口方法和全局常量的时候就算没有写上public,那么最终的访问权限也是public,注意不是default。
抽象类和接口的异同
1.抽象类要被子类继承,接口要被类实现
2.接口只能做方法声明,抽象类中可以作方法声明,也可以做方法实现。
3.接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。
4.接口是设计的结果,抽象类是重构的结果。
5.抽象类和接口都是用来抽象具体对象的,但是接口的抽象级别最高。
6.抽象类可以有具体的方法和属性,接口只能有抽象方法和不可变常量。
7.一个抽象类只能继承一个抽象父类,而接口可以继承多个接口;一个子类只能继承一个抽象类,却可以实现多个接口(在Java中,接口的主要功能是解决单继承局限问题)
比较点 | 抽象类 | 接口 |
关键字 | abstract class | interface |
字段 | 无限制 | 必须是public、static和final的 |
方法 | 既可以含普通方法,也可以含抽象方法 | 只能含抽象方法,且必须是public的 |
继承/实现 | 只能被类或抽象类继承 | 既可以被接口继承,也能被类或抽象类实现 |
多重继承 | 不支持 | 可以继承多个父接口 |
构造方法 | 子类通过构造方法链调用构造方法,抽象类不能用new操作符实例化 | 没有构造方法 |