抽象类
为什么要有抽象类?(主要的方向是:安全)
- 假如不知方法如何实现,写一个空方法体不就行了嘛?不,我希望不仅仅局限于此,我希望子类必须重写该方法(即抽象方法)
- 如果某个类的作用主要是为他的派生类提供一组通用接口,且这个类的对象毫无意义,如Instrument乐器类,那我就强制不能生成该类对象,不然会报错,这可以引导使用者正确的使用他们(即“应该使用抽象类的实现类”让事情难以做错),这便是抽象类
使用抽象类的好处
- 它是接口与实现类的一座桥梁
有个接口叫FlyAnimalAction,里面有flying方法和eat方法
有个类叫做蚊子,蚊子要实现flying和eat方法
有个类叫做苍蝇,苍蝇要实现flying和eat方法
然后你会发现所有飞行动物都要实现这两个接口,很是麻烦
此时抽象类的作用就出来了,创建一个FlyAnimal抽象类,然后实现上述接口
在抽象类中实现flying方法,因为大多数动物的飞行动作都是一样
而eat方法则是写成抽象方法,因为大多数动物吃东西的动作是不同的
然后,我们重新设计那两个类就很简单了
我们只需要继承那个FlyAnimal抽象类,实现eat方法方法即可
抽象类规则
- 普通类没有抽象方法也可以被声明为抽象类,而如果一个类有至少一个抽象方法,则是必须要被声明成抽象类
- 抽象类不能new,其他与普通类相同(但他可以有实例变量,可以自定义构造函数)
- 子类必须实现抽象方法,且不可忽略(不然他也是抽象类)
抽象类的特性
- 普通类对应实现,接口对应接口,而抽象类则是普通类与接口之间的,普通类》抽象类》接口
接口
定义:接口是比抽象类更加抽象,他是完全抽象的类,只提供接口部分,没有任何具体实现
为什么需要接口?
- 我们希望指明多个相关或者是不相关的对象的共同行为和特性
使用接口的好处
- 接口(和内部类)为我们提供了一种分离接口与实现更加结构化的方法
- 创建一个能够向上转型为多种基类的类型,来实现伪多重继承的特性
- 接口突破使用使用继承结构中的类的限制
接口规则
- 可以有实例变量,但是都是staic final的(看需求可知)
- 接口没有构造方法
使用继承扩展接口
- 使用extends来扩展,extends后面可以引用多个接口,当前类继承2个接口,当前类的派生类就能被看成2个接口的类型
public class Test {
public static void main(String[] args) {
InterfA i = new Sub();
i.hello1();
}
}
class Sub extends Sup {
}
class Sup implements InterfC{
@Override
public void hello3() {
System.out.println("hello C");
}
@Override
public void hello1() {
System.out.println("hello A");
}
@Override
public void hello2() {
System.out.println("hello B");
}
}
interface InterfA {
void hello1();
}
interface InterfB {
void hello2();
}
interface InterfC extends InterfA,InterfB{
void hello3();
}
组合接口时名字冲突
- 出现多个接口间函数函数相同,唯独返回类型不兼容,那么编译器会报错,只要返回类型兼容即可
适配接口(对应策略模式)
- 如Scanner类,他的构造函数接收一个Readable接口,那么只要我编写的类实现了Readable接口,作为Scanner构造器的传入,而不是被限制于某个特定类
接口中的域(实例变量):都是static final的
嵌套接口
- 接口中可以嵌套接口,但是在接口中的接口不能是私有的
- 接口可以在另一个类A中,
- 可以是private接口,就只能让那个类的其他内部类A.A1,A.A2去实现私有接口,因为其他类访问不到
- 也可以是public接口,那就可以通过A来访问了
接口与工厂
对于创建类,几乎在任何时刻,都可以代替为创建一个接口和一个工厂
interface Game {
boolean move();
}
interface GameFactory {
Game getGame();
}
class Checkers implements Game {
private int moves;
@Override
public boolean move() {
System.out.println("checkers move "+moves);
return ++moves!=3;
}
}
class Chess implements Game {
private int moves;
@Override
public boolean move() {
System.out.println("chess move "+moves);
return ++moves!=4;
}
}
class GameFactoryImpl1 implements GameFactory{
@Override
public Game getGame() {
return new Checkers();
}
}
class GameFactoryImpl2 implements GameFactory {
@Override
public Game getGame() {
return new Chess();
}
}
//业务逻辑
public class Games {
public static void playGame(GameFactory gameFactory) {
Game game=gameFactory.getGame();
while (game.move()) {
//具体的业务
}
}
public static void main(String[] args) {
playGame(new GameFactoryImpl1());
playGame(new GameFactoryImpl2());
}
}
接口与抽象类之间的关系
- 接口与抽象类是配合而非替代关系,接口负责方法声明,而抽象类则是提供默认实现,实现部分方法
- 常见的搭配有
- Collection接口和对应的AbstractCollection抽象类
- List接口和对应的AbstractList抽象类
- Map接口和对应的AbstractMap抽象类