抽象类和接口
1.抽象类
抽象类官方说明:
https://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.1.1.1
中写到抽象类是包含了抽象方法的类,其实这句话的说法是不准确的,必须如下面这个类
public abstract class ClassName {
void showWeather(String str) {
System.out.println("今天天气不错"+str);
}
abstract void showName();
}
其中抽象方法showName()可以不要,但是如果抽象类中定义的方法不是抽象方法,则一定要被实现。
但是抽象类和抽象方法必须用abstract修饰
抽象类是将将某几个具有相同属性或方法的普通类进行的抽象,因此抽象类就是为了继承而存在的。如果创建了一个抽象类但是却没有子类去继承它,则这个类就没有存在的意义了。如果一个父类的它的某个方法没有具体的实现,但是必须在子类中进行不同的实现,那么这个就可以吧这个方法抽象出来,抽象出一个抽象类来。
包含抽象方法的类称为抽象类,但是抽象类中不是只有抽象方法,它也可以想普通类一样具有成员变量和普通的成员方法。
抽象类和普通类的区别:
1.抽象方法必须使用public或者protected修饰,缺省的情况下默认是public(如果使用private不能被子类所继承,就没有意义,同时JAVA编译器也编译不过去)
2.抽象类不能被实例化,如果抽象类中有普通方法,创建的是匿名内部类,而不是实例化。
3.如果一个类继承了一个抽象类,则必须实现抽象类的所有抽象方法,否则必须将子类也定义为抽象类。
2.接口
接口英文名是interface,在软件工程中,接口泛指供他人调用的方法或者函数,接口的一般定义形式是:
public interface InterfaceDemo {
void show();
}
接口可以含有变量和方法,但是接口中的变量和方法会被隐式的指定为public static final变量(只能是public static final,如果使用private会报错),方法会被隐式的指定为public static只能是public abstract修饰(如果使用private,protected,static 等修饰编译会报错),且接口中所有的方法都不能被实现。既接口中的方法必须的抽象方法。因此可以把接口理解成一个极度抽象的抽象类。且一般情况下不会在接口中定义变量
public class InterfaceTest implements InterfaceOne ,InterfcaeTwo,... {
}
一个类可以实现多个接口,但是只能继承一个抽象类或者父类
3.抽象类和接口的比较
参数抽象类接口
默认的方法实现它可以有默认的方法实现接口完全是抽象的。它根本不存在方法的实现
实现子类使用extends关键字来继承抽象类。如果子类不是抽象类的话,它需要提供抽象类中所有声明的方法的实现。子类使用关键字implements来实现接口。它需要提供接口中所有声明的方法的实现
构造器抽象类可以有构造器接口不能有构造器
与正常Java类的区别除了你不能实例化抽象类之外,它和普通Java类没有任何区别接口是完全不同的类型
访问修饰符抽象方法可以有public、protected和default这些修饰符接口方法默认修饰符是public。你不可以使用其它修饰符。
main方法抽象方法可以有main方法并且我们可以运行它接口没有main方法,因此我们不能运行它。
多继承抽象方法可以继承一个类和实现多个接口接口只可以继承一个或多个其它接口
速度它比接口速度要快接口是稍微有点慢的,因为它需要时间去寻找在类中实现的方法。
添加新方法如果你往抽象类中添加新的方法,你可以给它提供默认的实现。因此你不需要改变你现在的代码。如果你往接口中添加方法,那么你必须改变实现该接口的类。
4.一个典型的实例
网上流传最广的实例是门和警铃的实例,首先所有的门都具有打开open和关闭close的功能,因此可以分别定义一个抽象类和接口
抽象类
public abstract class ClassDoor {
public abstract void open();
public abstract void close();
}
接口
public interface InterfaceDoor {
void open();
void close();
}
这时两者没有太大的区别,但是有些特殊的门需要有门禁功能,因此需要将这个功能也要添加到里面去
如果将门禁或者警铃的功能也放在抽象类里面,则只要是几次了这个抽象类的子类都要实现这三个功能,而大多数的门是不需要门禁或警铃的,因此不太合适
但是呢,可以将这个方法放在接口中就可以解决这个功能,只需要重新定义一个接口,在某些需要门禁或者警铃的门中实现这个接口即可,既:
public interface InterfaceDoorAlarm {
void alarm();
}
如果不需要警铃的门
方法1:
public class CommonDoor implements InterfaceDoor {
@Override
public void open() {
}
@Override
public void close() {
}
}
方法2
public class CommonDoor extends ClassDoor{
@Override
public void open() {
}
@Override
public void close() {
}
}
需要警铃的或者门禁的门
public class NeedAlarmDoor implements InterfaceDoor, InterfaceDoorAlarm {
@Override
public void open() {
}
@Override
public void close() {
}
@Override
public void alarm() {
}
}
优点和意义
interface:主要针对于功能、动作。将拥有这些动作的类实现此接口如:鸟、飞机都能fly();
体现了开闭原则:对修改关闭,对扩展开放;
abstract class:将拥有共同属性 特征的类继承此类,父类中添加新方法时子类将全部拥有而不用逐一去新增。
当子类拥有父类中的特性是便可以去extends,体现了代码的复用性。继承——灵活性;实现——严谨性;