1 抽象类
通常可以说四边形具有4条边,或者更具体一点,平行四边形是具有对边平行且相等特性的特殊四边形,等腰三角形是其中两条边相等的三角形,这些描述都是合乎情理的,但对于图形对象却不能使用具体的语言进行描述,它有几条边,究竟是什么图形,没有人能说清楚,这种类在Java中被定义为抽象类。
在解决实际问题时,一般将父类定义为抽象类,需要使用这个父类进行继承与多态处理。在多态机制中,并不需要将父类初始化对象,我们需要的只是子类对象,所以在Java语言中设置抽象类不可以实例化对象,因为图形类不能抽象出任何一种具体图形,但它的子类却可以。
抽象类的语法如下∶
public abstract class Test{ abstract vold testAbstract); } //定义抽象方法
其中,abstract 是定义抽象类的关键字。 使用 abstract关键字定义的类称为抽象类,而使用这个关键字定义的方法称为抽象方法。抽象方法没有方法体,这个方法本身没有任何意义,除非它被重写,而承载这个抽象方法的抽象类必须被继承,实际上抽象类除了被继承之外没有任何意义。
只要类中有一个抽象方法,此类就被标记为抽象类。
抽象类被继承后需要实现其中所有的抽象方法,也就是保证相同的方法名称、参数列表和相同返回值类型创建出非抽象方法,当然也可以是抽象方法。
抽象类继承关系
public abstract class Animal {
String name;
public Animal(String name) {
this.name = name;
}
public Animal(){}
/*
抽象方法
不能拥有方法体
*/
public abstract void run();
public void show(){
System.out.println("Animal show()");
}
}
public abstract class Dog extends Animal {
public abstract void lookHome();
}
public class SmallDog extends Dog {
@Override
public void lookHome() {
System.out.println("lookHome");
}
@Override
public void run() {
System.out.println("run......");
}
@Override
public void show() {
System.out.println("smallDog show()");
}
}
总结:
1.当一个类继承了一个抽象类 则必须【实现】抽象类中的抽象方法 或者 将 实现类也变为抽象类
2.抽象类中可以存在普通的属性 也可以存在普通的方法
3.抽象类中可以没有抽象方法
4.抽象方法只能存在抽象类内
5.子类需要实现所有的抽象方法 不仅是父亲的 爷爷的也要实现
6.抽象类不能创建对象 需要借助子类实现功能
2. 接口
接口是抽象类的延伸,可以将它看作是纯粹的抽象类,接口中的所有方法都没有方法体。接口就是规范,定义的是一组规则,体现了现实世界中“如果你是…则必须能…”的思想。如果你是天使,则必须能飞。如果你是汽车,则必须能跑。接口的本质是契约,就像我们人间的法律一样。制定好后大家都遵守。
2.1 接口
声明格式:
[访问修饰符] interface 接口名 [extends 父接口1,父接口2…] { 常量定义; 方法定义; } |
定义接口的详细说明:
- 访问修饰符:只能是public或默认。
- 接口名:和类名采用相同命名机制。
- extends:接口可以多继承。
- 常量:接口中的属性只能是常量,总是:public static final 修饰。不写也是。
- 方法:接口中的方法只能是:public abstract。 省略的话,也是public abstract。
要点
|
*实例:
需求:飞机、鸟、超人,导弹参加飞行表演。
思路1:定义一个父类Flyable,让飞机、鸟、超人,导弹都继承该类。不可以,因为继承表达的是is-a的关系,而飞机、鸟、超人不是一种事物,
思路2:使用接口,定义一个接口Flyable,让飞机、鸟、超人,导弹都实现该接口。接口表达是has-a的关系
接口: 定义了一种规范 表示 has a的关系
1.如何声明接口 权限修饰符 interface 接口名
2.接口中的方法是抽象方法 ?
3.一个类实现了接口 则 必须实现 接口内的方法 否则 此类 要变为 抽象类
4.当一个类实现了接口 则 此类可以作为此接口的子类存在
5.一个类可以实现多个接口 必须实现各个接口中的方法 否则 此类变为抽象类
6.一个接口可以继承多个接口 实现此接口的额类 需要 实现各个接口内的方法 否则 将此类变为抽象类
7.接口中的变量 是全局静态 常量
默认被 public staic final 修饰
8.接口内的方法 默认被 public abstract 修饰
/*接口: 定义了一种规范 表示 has a的关系
1.如何声明接口 权限修饰符 interface 接口名
2.接口中的方法是抽象方法 ?
3.一个类实现了接口 则 必须实现 接口内的方法 否则 此类 要变为 抽象类
4.当一个类实现了接口 则 此类可以作为此接口的子类存在
5.一个类可以实现多个接口 必须实现各个接口中的方法 否则 此类变为抽象类
6.一个接口可以继承多个接口 实现此接口的额类 需要 实现各个接口内的方法 否则 将此类变为抽象类
7.接口中的变量 是全局静态 常量
默认被 public staic final 修饰
8.接口内的方法 默认被 public abstract 修饰*/
public interface Fly {
public final static String NAME = "FLY";
void fly(); //public abstract
}
public interface SaveWord {
public void savaWorld();
}
public class Daodan implements Fly {
@Override
public void fly() {
System.out.println("导弹 会飞 ");
}
}
public abstract class FeiJi implements TwoInOne {
}
public class SuperMan implements Fly,SaveWord {
@Override
public void fly() {
System.out.println("超人会飞");
}
@Override
public void savaWorld() {
System.out.println("拯救世界");
}
}
public class Test {
public static void main(String[] args) {
Fly daodan = new Daodan();//多态
daodan.fly();
SuperMan superMan = new SuperMan();
SaveWord sp = new SuperMan();
sp.savaWorld();
superMan.fly();
System.out.println(superMan.NAME);
}
}
2.2 接口新特征
JDK7及其之前
- 接口的变量都是public final static 全局静态常量,无变化
- 接口中都是抽象abstract方法,不能有static方法(因为abstract和static、final、private不能共存)
JDK8及其之后
- 接口中可以添加非抽象方法(static),实现类不能重写,只能通过接口名调用。
- 如果子类中定义了相同名字的静态方法,那就是完全不同的方法了,直接从属于子类。可以通过子类名直接调用
- 接口中可以添加非抽象方法(default),实现类可以重写,只能通过对象名调用
- 实现类可以直接使用default方法,可以重写default方法,但是必须去掉default。(default只能接口中使用)
- 上级接口中default方法的调用:MyInterface.super.method2()
提供非抽象方法的目的
- 为了解决实现该接口的子类代码重复的问题
- 为了既有的成千上万的Java类库的类增加新功能,且不必对这些类重新进行设计。比如只需在Collection接口中增加default Stream<E> stream(),相应的Set和List接口以及它们的子类都包含此的方法,不必为每个子类都重新copy这个方法。
JDK9及其之后
接口中可以定义private的非抽象方法,便于将多个方法中的冗余代码进行提取,并且不对外公开。减少冗余、也实现了代码隐藏。
2.3 面向接口编程
面向接口编程是面向对象编程的一部分。
为什么需要面向接口编程? 软件设计中最难处理的就是需求的复杂变化,需求的变化更多的体现在具体实现上。我们的编程如果围绕具体实现来展开就会陷入”复杂变化”的汪洋大海中,软件也就不能最终实现。我们必须围绕某种稳定的东西开展,才能以静制动,实现规范的高质量的项目。
接口就是规范,就是项目中最稳定的核心! 面向接口编程可以让我们把握住真正核心的东西,使实现复杂多变的需求成为可能。
通过面向接口编程,而不是面向实现类编程,可以大大降低程序模块间的耦合性,提高整个系统的可扩展性和和可维护性。
面向接口编程的概念比接口本身的概念要大得多。设计阶段相对比较困难,在你没有写实现时就要想好接口,接口一变就乱套了,所以设计要比实现难!