抽象类
class Shape {
public void draw() {
// 啥都不用干
}
}
class Cycle extends Shape {
@Override
public void draw() {
System.out.println("○");
}
}
class Rect extends Shape {
@Override
public void draw() {
System.out.println("□");
}
}
class Flower extends Shape {
@Override
public void draw() {
System.out.println("♣");
}
}
/华丽丽的分割线//
// Test.java
public class Test {
public static void main(String[] args) {
Shape shape1 = new Flower();
Shape shape2 = new Cycle();
Shape shape3 = new Rect();
drawMap(shape1);
drawMap(shape2);
drawMap(shape3);
}
// 打印单个图形
public static void drawShape(Shape shape) {
shape.draw();
}
}
看完上面代码可以发现,父类Shape
中的draw();
方法并没有实现具体的功能,代码中调用的draw();
都是基于子类的draw();
方法来完成的,这种方法就可以定义为抽象方法(abstract method),包含抽象方法的类就叫做抽象类(abstract class).
abstract
用abstract关键字来标识抽象方法和抽象类
abstract class Shape {
abstract public void draw();
}
注意:
- 抽象类中不能有具体的实现,所以
abstract public void draw();
后面不可以带{}
,切记 - 包含抽象方法的类叫做抽象类
- 抽象类中可以有抽象方法 也可以有非抽象方法或成员变量
- 抽象类是不能被实例化的(不能被new)。
要想使用只能创建该抽象类的子类 然后让子类重写抽象类中的抽象方法 - 所以可以说抽象类就是为了被继承的,要注意一旦被继承之后一定要重写抽象类里的方法
- 但如果是抽象类A继承抽象类B, A选择可重写也可不重写B中的方法
- 如果抽象类中的方法已经重写了,那么被继承之后就不用重写
- 抽象方法不能是私有的
抽象类的作用
抽象类的存在就相当于多了一层代码的校验,像Shape
这样的类我们并不会直接使用, 而是使用它的子类. 万一不小心创建了Shape
的实例, 编译器会及时提醒我们.
比如说上述绘制图形的代码
如果说本意是想绘制方块,而编写代码时用的是父类Shape
的draw();
方法,这样编译器并不会报错,但是运行结果并不是我们想要的,排查错误时不易被发现
但如果我们将draw();
方法设置为抽象方法,由于抽象类无法实例化,所以无法调用里面的draw();
方法,这样就可以预防我们出错
接口
接口是抽象类的更进一步. 抽象类中还可以包含非抽象方法, 和字段. 而接口中包含的方法都是抽象方法, 字段只能包含静态常量
比如说打印图形的代码,如果Shape类中没有非抽象方法和字段,那么就可以将上面代码改写成
interface IShape {
void draw();
}
class Cycle implements IShape {
@Override
public void draw() {
System.out.println("○");
}
}
class Rect implements IShape {
@Override
public void draw() {
System.out.println("□");
}
}
class Flower implements IShape {
@Override
public void draw() {
System.out.println("♣");
}
}
interface
- 接口用关键字interface定义
- 接口中的方法全部不能有具体的实现==》接口中的方法默认都是抽象方法,即默认是public abstract,所以可以省略不写
- 接口当中的方法要尽量简洁
- 接口中的成员变量默认是public static final的 所以必须要初始化
- 接口不能单独被实例化 不可以new==>接口存在的意义就是被是实现/继承
- 接口名一般是以i开始
public interface IShape
implements
class Rect implements IShape{}
,用关键字implements实现接口- 类和接口之间的关系叫实现 只要一个普通类要实现这个接口,那么接口当中的方法必须重写
- 接口可以发生向上转型
IShape iShape=new Rect();
接口的作用
-
接口的存在是为了实现Java中的多继承
class Abc implements IA,IB,IC。。。
或是class Cat extends Animal implements IRunning
-
接口和接口之间不能实现但是可以继承,且可以继承多个接口
抽象类和接口的使用
单从关键字上看extends
vs implements
,一个是拓展,一个是实现,拓展是指之前已经存在,将他更完善,而实现是之前没有,要重新构造出来一个
所以继承表达的意思是is-a
,而实现接口表达的是具有某种特性
还是用代码来举例子
先创建一个Animal类
class Animal {
protected String name;//这里之所以用protected来实现封装上篇已经提到,此处就不赘述
public Animal(String name) {
this.name = name;
}
}
再创建几个接口
interface IRunning {
void run();
}
interface IEating {
void eat();
}
此时创建一个猫咪类,他首先是一个动物(extends Animal),其次猫咪可以跑来跑去,可以吃东西(也就是说有会跑会吃的特点)(implements IRunning,IEating),这样一个猫咪类就建好了
class Cat extends Animal implements IRunning,IEating {
public Cat(String name) {
super(name);
}
@Override
public void run() {
System.out.println(this.name + "is running");
}
@Override
public void eat() {
System.out.println(this.name + "is eating");
}
}
抽象类和接口的区别
- 核心区别:
抽象类中可以包含非抽象方法, 和字段. 那么普通方法和字段可以被子类直接使用(不必重写)
接口中包含的方法都是抽象方法, 字段只能包含静态常量,所以子类必须重写所有的抽象方法 - 一个抽象类可以实现多个接口
接口不能继承抽象类,但是接口可以用extends关键字继承多个父接口