抽线类与普通类相比最大的特点是约定了子类的实现要求,但是抽象类有一个缺点:单继承,如果要想约定子类的实现要求以及避免单继承的局限就需要使用接口。设计中可以使用抽象类和接口,接口优先选择。
接口的基本概念
接口就是一个抽象方法和全部常量的集合,在Java中可以使用interface
关键字来进行定义。
范例: 定义一个接口
//因为接口和类的定义命名要求相同,所以为了区分
//建议在接口前面追加一个字母I
interface IMessage {
public static final String MSG = "blog.isohard.cn";
public abstract void print();
}
如果子类要使用接口,那么利用implements
关键字来实现接口,同时一个子类可以实现多个接口,也就是利用接口实现多继承的概念,对于接口的子类(如果不是抽象类)则必须重写接口中的全部抽象方法,随后可以利用子类的向上转型通过实例化子类来得到接口的实例化对象。
interface IMessage {
public static final String MSG = "blog.isohard.cn";
public abstract void print();
}
interface INews {
public abstract String get();
}
//一个类现在可以实现多个接口
class MessageImpl implements IMessage, INews {
public void print() {
System.out.println(IMessage.MSG);
}
public String get() {
return IMessage.MSG; //访问常量都建议加上类名称
}
}
public class TestDemo {
public static void main(String[] args) {
IMessage m = new MessageImpl(); //子类为父接口实例化
m.print();
}
}
当一个子类继承了多个接口之后,并且接口对象通过子类进行实例化,那么多个父接口之间允许互相转换。
接口的使用限制
接口一旦定义完成之后就需要对其有一个核心的说明,首先需要说明的是:接口里面只允许存在有public权限,也就是说不管是属性还是方法其权限永远都是public。
范例: 错误的重写
interface INews {
abstract String get(); //即使不谢public,也是public
}
class NewsImpl implements INews {
String get () {
//权限更加严格了,所以无法重写
return "blog.isohard.cn";
}
}
所以方法尽量使用public定义。
另外优于接口之中只是全局常量和抽象方法的集合,所以一下的两种的定义形式的效果都是一样的。
interface INews {
public static final String MSG = "blog.isohard.cn";
public abstract String get();
}
interface INews {
String MSG = "blog.isohard.cn";
String get();
}
在编写接口的时候,基本上接口里面只会提供抽象方法,很少有许多的全局常量。所以为了避免出现混乱,接口的方法往往都要加上public。
当一个子类需要实现接口又需要继承抽象类的时候,先使用extends
继承一个抽象类,在使用implements
实现多个接口。
范例: 子类继承抽象类和实现接口
interface INews {
public String get();
}
abstract class AbstractMessage {
//抽象类命名一般在前加上Abstract
public abstract void print();
}
class NewsImpl extends AbstractMessage implements INews {
public String get() {
return "isohard.cn";
}
public void print(){