抽象类的主要功能是为了在实现多态过程中,避免错误的创建了父类实例对象而提供的语法支持。
在标准的多态实践中,父类仅仅是为子类提供了一个模板,子类提供具体实现。父类也是一个普通类的情形下,创建出一个父类的对象是没有意义的。他没有具体的方法实现。
abstract void f(); 仅有声明而没有方法体的方法。
class 前有abstract修饰的类为抽象类
接口是抽象方法的一种极端形式,要求所有的方法都是抽象方法
除了为了更方便的实现多态,更为了突破JAVA的单继承限制,实现一种隐式的多继承(内部类)
用interface关键字而不是class关键字标明的类,其中可以有属性,只能有抽象方法(提供方法名,确定参数列表和返回值),却不给任何实现。
JAVA允许一个类单继承自一个实体类或者是抽象类,但是可以多实现多个接口。
public class Actor {
public void fight(){
System.out.println("do nothing");
};
}
public interface CanFight {
void fight();
}
public interface CanFly {
void fly();
}
public interface CanSwim {
void swim();
}
public class ActActor extends Actor implements CanFight,CanFly,CanSwim {
@Override
public void fly() {
}
@Override
public void swim() {
}
}
public class Test {
public static void a(Actor actor) {
actor.fight();
}
public static void b(CanFight canFight) {
canFight.fight();
}
public static void c(CanFly canFly) {
canFly.fly();
}
public static void d(CanSwim canSwim ) {
canSwim.swim();
}
public static void main(String[] args) {
ActActor actActor = new ActActor();
a(actActor);
b(actActor);
c(actActor);
d(actActor);
}
}
上面的例子中注意fight()方法并没有在ActActor中做实现,这是因为Actor类中已有实现
如果将Actor类中的fight()方法改为非public的,那么ActActor就相当于未对CanFight中的fight()方法做实现,此时编译会出错。
如果Actor类中没有fight()方法,但是Actor继承自Human类,Human类中有fight()方法,那么此时也是可以的。
此处示例也说明了接口的两个用处
类可以实现接口,接口可以继承接口并且可以多继承接口
public interface Monster {
void menace();
}
/**
* 接口之间用继承
*/
public interface DangerousMonster extends Monster {
void destory();
}
public interface Lethal {
void kill();
}
/**
* 接口可以多继承接口,只要用逗号隔开就行。
*/
public interface Vampire extends DangerousMonster,Lethal {
void drinkBlood();
}
public class VeryBadVampire implements Vampire {
@Override
public void drinkBlood() {
}
@Override
public void destory() {
}
@Override
public void kill() {
}
@Override
public void menace() {
}
}
前面讲过如果某个类的父类和其实现的接口都有同一个方法的时候,这个类可以不用再对该方法做实现。
但是如果多个接口,其中都有同一个方法,导致重载与覆盖同时发生,这时候可能就会发生错误。
public interface InterfaceA {
void f();
}
public class Father {
public int f(){}
}
/**
* 如下写法的子类会提示编译错误,因为方法必须override,但是又会与父类的方法冲突(同名,同参数列表,就返回值不同,不是overload,所以会提示编译错误)
*/
public class Son extends Father implements InterfaceA {
}
接口中的属性如果是基本数据类型,他们都要大写,都是编译器常量,可以拿来替代枚举使用
接口中定义的域是不能为空final的,但是可以被非常量表达式初始化
这些属性不是接口的一部分,他们的值会存储在接口的静态存储区域内
import java.util.Random;
public interface RandVals {
Random RAND = new Random(47);
int RANDOM_INT = RAND.nextInt(10);
long RANDOM_LONG = RAND.nextLong() * 10;
}
接口可以嵌套在类或者其他接口中
public class OuterClass {
//1.类内部接口可以是包访问权限
interface B{
void f();
}
//1.1. 对应的实现类可以是public的
public class BImpl implements B{
public void f(){}
}
//1.2. 对应的实现类可以是private的
private class BImpl2 implements B{
public void f(){}
}
//1.3. 对应的实现类可以是默认访问权限的
class BImpl3 implements B{
public void f() {
}
}
//2. 类内部接口可以是包访问权限
public interface C{
void f();
}
//2.1. 对应的实现类可以是public的
public class CImpl implements C{
public void f(){}
}
//2.2. 对应的实现类可以是private的
private class CImpl2 implements C{
public void f(){}
}
//2.3. 对应的实现类可以是默认访问权限的
class CImpl3 implements C{
public void f() {}
}
//2. 类内部接口可以是private的
private interface D{
void f();
}
//2.1. 对应的实现类可以是public的
public class DImpl implements D{
public void f(){}
}
//2.2. 对应的实现类可以是private的
private class DImpl2 implements D{
public void f(){}
}
//2.3. 对应的实现类可以是默认访问权限的
class DImpl3 implements D{
public void f() {}
}
}
原文:https://www.cnblogs.com/Pikzas/p/11306424.html