一、抽象类(abstract)
1、定义
在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类,使用abstract关键词来修饰。
abstract修饰的类就叫做抽象类。
abstract修饰的方法就叫做抽象方法。
通俗的讲:当你无法用足够的信息去描述一个对象,这样的类称为抽象类。列如我们可以定义一个形状的类,但是形状有无数个,因此我们将它可以定义成为一个抽象类。
2、使用方法
使用定义中的例子定义一个形状的抽象类(示例):
abstract class Shape{ //定义一个形状的类
protected Shape(){ //构造器构造器,一般定义为protected(后面讲原因) }
public abstract double countPerimeter(); //定义一个计算周长的抽象方法
public abstract double countArea(); //定义一个计算面积的抽象方法
public abstract String getType(); //定义一个获取形状类型的抽象方法
public void func(){ //定义一个普通方法也是可行的
System.out.println("func");
}
}
3、使用规则
- (1)抽象类不能实例化对象,不能使用new操作符创建对象
- (2)抽象类的其他功能都与普通类一样
- (3)抽象类中可以定义构造器,但是不可以用来实例化对象,只能在子类中使用,所以该构造器一般定义为protected
因此我们要实现抽象类中的方法就需要用到子类来重写它
代码如下(使用矩形举例说明):
abstract class Shape{ //定义一个形状的类
protected Shape(){ //构造器构造器,一般定义为protected(后面讲原因) }
public abstract double countPerimeter(); //定义一个计算周长的抽象方法
public abstract double countArea(); //定义一个计算面积的抽象方法
public abstract String getType(); //定义一个获取形状类型的抽象方法
public void func(){ //定义一个普通方法也是可行的
System.out.println("func");
}
}
class Rectangle extends Shape{ //矩形子类继承父类形状类
private double length;//长度
private double width;//宽度
@Override //重写父类中计算周长的方法
public double countPerimeter() {
return (length + width) * 2;
}
@Override //重写父类中计算面积的方法
public double countArea() {
return length * width;
}
@Override
public String getType() { //重写获取形状类型
return "矩形";
}
总结
- (1)有抽象方法的类一定是抽象类,抽象类中的方法可以不是抽象的;
- (2)抽象类中可以有普通成员变量;
- (3)抽象类可以有构造方法(这里的构造方法可以为普通的也可以为抽象的);
- (4)抽象类中的抽象方法的访问类型可以是 public,protected,一般使用protected;
二、接口(interface)
1、定义
可以看做是一种特殊的抽象类,可以指定一个类必须做什么,而不是规定它如何去做。
2、使用方法
定义一个抽象的椅子类(示例):
abstract class chair { //定义一个抽象的椅子类
public void sit() { //椅子都有可以坐下的方法
}
}
interface turningChair { //定义一个旋转椅的接口
void turing(); //旋转椅的旋转方法
}
interface deckChair{ //定义一个躺椅的接口
void deck(); //躺椅躺下的方法
}
我们从中不难看出抽象类与接口的区别
- 坐下指的是"是"的关系,所以可以定义在抽象类当中;
- 旋转椅/躺椅指的是"含有"的关系,所以就需要定义在接口当中;
3、使用规则
- 1)不能够new创建对象
- 2)如果要去创建一个接口对应的对象,则需要通过它的具体实现类,使用implements关键字去实现接口
- 3)接口被编译之后也会产生对应的字节码文件
- 4)接口之间也是可以相互继承 extends
- 5)接口对应是多实现 eg.class C implements A,B
椅子接口的完善:单实现和多实现(代码如下):
interface turningChair { //定义一个旋转椅的接口
void turing(); //旋转椅的旋转方法
}
interface deckChair{ //定义一个躺椅的接口
void deck(); //躺椅躺下的方法
}
class turningChair1 implements turningChair{ //单实现接口旋转椅
@Override
public void turing() { //重写旋转方法
System.out.println("旋转");
}
}
class chair2 implements turningChair,deckChair{ //多实现接口椅子
@Override
public void turing() { //重写旋转方法
System.out.println("旋转");
}
@Override
public void deck() { //重写躺下方法
System.out.println("躺下");
}
}
提醒事项
1、接口中定义的属性是static final的可省略不写,也就是说代码中的void turning();
完整的应该是public static final void turning();
原因如下:
- static 原因主要是接口的实现是多实现,为了区分不同接口当中的相同变量
- final 原因是因为如果是变量,接口的存在就失去其意义,同时接口来说指的是统一的协议,Java设计者直接规定接口中的属性只能是public static final的
2、JDK1.8引入的新特性:
- (1)引入了default关键字提供默认接口方法,一个默认接口方法可以有默认的
作用: - 帮助扩展接口,而不需要破坏实现类
- 接口和抽象类之间差异更小一点
- 实现类可以自己决定覆盖哪个默认方法实现
- 为了支持lambda表达式
- (2)允许接口中存在静态的公有方法
作用: - 可以用于提供一些合法性检查的逻辑
- 静态方法不允许类重写,重写就会被覆盖,更加安全
总结
- (1)接口中没有普通成员变量
- (2)接口中不能有构造方法
- (3)接口中的所有方法必须都是抽象的,不能有非抽象的普通方法
- (4)接口中的抽象方法只能是 public 类型的,并且默认即为 public abstract 类型
- (5)一个类可以实现多个接口
三、抽象类和接口的区别
-
(1)抽象类中可以有普通成员变量,接口中没有普通成员变量
-
(2)抽象类可以有构造方法,接口中不能有构造方法
-
(3)抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。
-
(4)抽象类中的抽象方法的访问类型可以是 public,protected ,但接口中的抽象方法只能是 public 类型的,并且默认即为 public abstract 类型
-
(5)一个类可以实现多个接口,但只能继承一个抽象类。
-
(6)抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只是public static final 类型,并且默认即为 public static final 类型。