【Java】接口

在Java中,接口和抽象类为我们提供了一种将类的对外接口与实现分离的更加结构化的方法。下面将介绍抽象类,它是普通的类与接口之间的一种中庸之道,接着再介绍接口。

抽象类和抽象方法

当我们仅是希望有一个基类可以提供统一的接口去控制它导出的所有子类,并且该基类没有被实例化的必要时,我们就可以使用抽象类去创建这个基类。为了使抽象类不被实例化,我们就需要使用某种机制来限制。于是,Java中提供一种叫做抽象方法的机制(相当于C++中的纯虚函数),这种方法是不完整的:仅有声明而没有方法体。

abstract void fun(); //抽象方法声明语法

抽象类如果包含抽象方法,那么抽象类就是不完整的,试图产生该类的对象的时候,编译器就会抛出错误信息。

所以,我们就将包含抽象方法的类叫做抽象类。当然,如果一个类包含一个或者多个抽象方法,该类就必须被限定为抽象的。并且使用关键字abstract来限定。

需要注意,Java中的抽象类中除了包含抽象方法也可以包含具体的数据和具体的方法,但是为了程序的清晰度,抽象类中方法最好还是全是抽象方法。如果子类继承自某一个抽象类,并且想创建子类的对象,那么抽象类中的所有抽象方法在子类中都要被实现。否则,子类仍旧是一个抽象类,无法被实例化。

一个抽象类举例:

public abstract Animal{ private String name; public abstract void eat(); public String toString { return name;} } 接口

如果说abstract关键字使得可以在类中创建一个或多个没有方法体的方法给类提供了抽象的概念,那么interface关键字就使得类的抽象更前一步。

使用interface关键字产生的类是一个完全抽象的类,其中的方法没有任何具体实现。即,只允许创建者确定类中的方法名、参数列表和返回类型,但是没有任何方法体。

一个类如果使用了某个接口那么就必须得实现该接口中规定的所有方法,这倒像是“要干什么事,就必须遵守某种协议”一样。

通常,为使一个方法可以在类间调用,两个类都必须出现在编译时间里,以便Java编译器可以检查以确保方法特殊是兼容的。这个需求导致了一个静态的不可扩展的类环境。在一个系统中不可避免会出现这种状况:函数在类层次中越堆越高以致该机制可以为越来越多的子类可用。

接口的设计避免了这个问题。它们把方法或方法系列的定义从类层次中分开。因为接口是在和类不同的层次中,与类继承层次无关的类实现相同的接口是可行的。这是实现接口的真正原因所在,接口可以使代码之间解除继承限制,降低代码耦合性。

接口的定义和实现

接口的创建同类创建一样,只需将class关键字替换为interface关键字,里面的方法只用声明不用实现即可。接口中也可以包含域,但是这些域都是隐式地为static和final的。要让某个类遵循某个接口(或者是一组接口)就需要使用implements关键字。

接口的定义

public interface USB{ String name = "USB"; public String getName(); }

访问权限修饰符可以为public也可以不写。接口中的方法不能设置成private的,让使用该接口的类不能够实现该方法,所以接口中方法都是默认地为public。接口中的域是static和final的,所以定义时一定要初始化。

接口的实现

一旦接口被定义,一个或多个类便可以实现该接口。为实现该接口,在定义的类名后使用implement接接口名,然后在类中实现接口定义的方法。

可以使用接口引用指向实现了接口的类对象,就类似于使用基类的引用指向子类对象,于是就可以实现多态功能。

public class Mouse implements USB{ //实现接口中定义的方法 public String getName(){ return "Mouse USB";} public static void main(String args[]){ USB usb = new Mouse(); //使用接口引用指向实现了接口的类对象 } }

接口的局部实现

如果一个类不完全实现一个接口中的方法那么该类就必须使用abstract修饰。也就是说,抽象类可以不完全实现接口中的方法。

完全解耦

只要一个方法操纵的是类而非接口,那么你就只能在这个类或其子类上使用这个方法。即只能操纵有继承关系的类。如果你将此方法应用于非此继承结构中的类,那么就会出问题。

若这个方法是接口中的,那么该方法便可以应用在实现了该接口的类对象上,不需要考虑类之间是否有继承性。这样就可以写出复用性更好的代码~

代码说明(参考[1]):

class Processor{ public String name() { return getClass().getSimpleName(); } Object process(Object input) { return input; } } class Upcase extends Processor{ @Override String process(Object input) { return ((String)input).toUpperCase(); } } class DownCase extends Processor{ @Override String process(Object input) { return ((String)input).toLowerCase(); } } public class Apply { //使用基类引用统一控制子类对象 public static void process(Processor p, Object s) { System.out.println("Using Processor " + p.name()); System.out.println(p.process(s)); } public static void main(String[] args) { String s = "This Road Is Long."; process(new Upcase(), s); process(new DownCase(), s); } }

Apply.process()方法使用基类引用去同一控制对象。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzjgdp.html