抽象类与抽象方法
随着继承层次中一个个新子类的定义,类变得越来越具体,而父类则更一般,更通用。类的设计应该保证父类和子类能够共享特征。有时将一个父类设计得非常抽象,以至于它没有具体的实例,这样的类叫做抽象类。在我们生活中很常见,比如,鸡鸭鱼狗,我们可以将其抽象成动物。
声明:
- 用abstract关键字来修饰一个类,这个类叫做抽象类。
- 用abstract来修饰一个方法,该方法叫做抽象方法。
√只有方法的声明,没有方法的实现。以分号结束。例如::public abstract void method();
要求:
- 抽象类不能被实例化(对象必须有具体的内容而抽象类含有不具体的内容)。
- 抽象类是用来被继承的,抽象类的子类必须重写父类的抽象方法,并提供方法体。若没有重写全部的抽象方法,仍为抽象类。
- 除了你不能实例化抽象类之外,它和普通Java类没有任何区别。但是抽象类中可能含有抽象函数。
- 抽象类关键字abstract不能和private、static、final共存(抽象类等着被子类重写所以不能使用private,我们在加载静态的时候,必须是具体的数据,而且如果static可以通过类名调用一个抽象方法当然是不行的,抽象类的方法等着子类去重写,用final修饰表示不可被修改,也是不行的。)
- 不能用abstract修饰变量、代码块、构造器。
- 抽象类中可以存在private属性和方法,但是不能被abstract同时修饰且子类无法访问。
public abstract class Animal {//抽象类
//变量声明和普通类一样
private String name;
static int age;
int id;
//final修饰的方法。
public final void getTime() {
long start = System.currentTimeMillis();
long end = System.currentTimeMillis();
System.out.println("执行时间是:" + (end - start));
}
//静态方法
public static void isAnimal() {
System.out.println("我是动物!");
}
public void sing(){//普通方法
System.out.println("我会叫!");
}
public abstract void eatFood();//抽象方法
public static void main(String[] args) {//抽象类中的main
Animal.isAnimal();//调用本类的静态方法
}
}
//=================================
class Dog extends Animal {
//重写抽象方法。
public void eatFood() {
System.out.println("我吃的是狗粮!");
}
public static void main(String[] args) {
Dog d = new Dog();
d.sing();//调用父类抽象类的普通方法
d.getTime();//调用父类抽象类final修饰的方法。
d.eatFood();//重写的方法
}
}
接口
接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法和常量值的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。
- 有时必须从几个类中派生出一个子类,继承它们所有的属性和方 法。但是,Java不支持多重继承。有了接口,就可以得到多重继承的效果。
- 有时必须从几个类中抽取出一些共同的行为特征,而它们之间又 没有is-a的关系,仅仅是具有相同的行为特征而已。例如:鼠标、键盘、打 印机、扫描仪、摄像头、充电器、MP3机、手机、数码相机、移动硬盘等都 支持USB连接。
- 接口就是规范,定义的是一组规则,体现了现实世界中“如果你是/要...则 必须能...”的思想。继承是一个"是不是"的关系,而接口实现则是 "能不能" 的关系。
- 接口的本质是契约,标准,规范,就像我们的法律一样。制定好后大家都 要遵守。
特点:
- 用interface来定义。
- 接口中的所有成员变量都默认是由public static final修饰的。
- 接口中的所有抽象方法都默认是由public abstract修饰的。
- 1.8新增默认方法和静态方法。
- 接口中没有构造器。不能有main函数。
- 接口采用多继承机制。
注意:
- 定义Java类的语法格式:先写extends,后写implements
- 一个类可以实现多个接口,接口也可以继承其它接口。
- 实现接口的类中必须提供接口中所有方法的具体实现内容,方可实 例化。否则,仍为抽象类。
- 接口的主要用途就是被实现类实现。
- 与继承关系类似,接口与实现类之间存在多态性。
- 接口和类是并列关系,或者可以理解为一种特殊的类。
public interface Phone{
void call();
static void playGame(){//静态方法
System.out.println("玩游戏");
}
default void listenMusic(){//默认方法
System.out.println("听歌");
}
}
class HuaWei implements Phone{
@Override
public void call() {
System.out.println("华为手机通话!");
}
public void listenMusic(){//默认方法
Phone.super.listenMusic();//调用接口的默认方法
System.out.println("用华为听歌");
}
public static void main(String[] args) {
Phone.playGame();//调用接口的静态方法
HuaWei huaWei = new HuaWei();
huaWei.call();
huaWei.listenMusic();//调用接口的默认方法
}
}
默认方法:Java8 允许在接口中增加默认方法,默认方法在实现类中可以不去实现它,但是如果接口中有默认方法,实现类将默认继承这个默认方法,当然如果有需要的话可以在实现类中覆盖抽象方法,所以很容易得出默认方法的使用方式:用实现类的实例来直接点出这个默认方法。而当被覆盖后,接口中的默认方法调用为:接口名.super.默认方法。
静态方法:允许在已有的接口中增加静态方法,需要提供方法的实现。静态方法属于接口本身,不被实现类所继承。所以说静态方法和普通的静态方法使用方式相同,直接使用接口的类名点方法名。
区别
参数 | 抽象类 | 接口 |
默认的方法实现 | 它可以有默认的方法实现 | 1.8后它可以有默认的方法实现 |
实现 | 子类使用extends关键字来继承抽象类。如果子类不是抽象类的话,它需要提供抽象类中所有声明的方法的实现。 | 子类使用关键字implements来实现接口。它需要提供接口中所有声明的方法的实现 |
构造器 | 抽象类可以有构造器 | 接口不能有构造器 |
与正常Java类的区别 | 除了你不能实例化抽象类之外,它和普通Java类没有任何区别 | 接口是完全不同的类型 |
访问修饰符 | 抽象方法可以有public、protected和default这些修饰符 | 接口方法默认修饰符是public。声明静态方法时使用default。 |
main方法 | 抽象方法可以有main方法并且我们可以运行它。 | 接口没有main方法,因此我们不能运行它。 |
多继承 | 抽象方法可以继承一个类和实现多个接口 | 接口只可以继承一个或多个其它接口 |
速度 | 它比接口速度要快 | 接口是稍微有点慢的,因为它需要时间去寻找在类中实现的方法。 |
添加新方法 | 如果你往抽象类中添加新的方法,你可以给它提供默认的实现。因此你不需要改变你现在的代码。 | 如果你往接口中添加方法(除静态方法和默认方法外),那么你必须改变实现该接口的类。 |