与这个问题相对应:Java中的接口是什么?
接口是抽象类的一种特殊形式,它不实现任何方法。在Java中,你可以这样创建一个接口:
interface Interface { void interfaceMethod(); }
由于该接口无法实现任何方法,因此这意味着整个事物(包括所有方法)都是公共的和抽象的(Java术语中的抽象含义是“未由此类实现”)。因此,上面的接口与下面的接口相同:
public interface Interface { abstract public void interfaceMethod(); }
要使用此接口,你只需要实现该接口。许多类可以实现一个接口,而一个类可以实现许多接口:
interface InterfaceA { void interfaceMethodA(); } interface InterfaceB { void interfaceMethodB(); } public class ImplementingClassA implements InterfaceA, InterfaceB { public void interfaceMethodA() { System.out.println("interfaceA, interfaceMethodA, implementation A"); } public void interfaceMethodB() { System.out.println("interfaceB, interfaceMethodB, implementation A"); } } public class ImplementingClassB implements InterfaceA, InterfaceB { public void interfaceMethodA() { System.out.println("interfaceA, interfaceMethodA, implementation B"); } public void interfaceMethodB() { System.out.println("interfaceB, interfaceMethodB, implementation B"); } }
现在,如果你愿意,可以编写如下方法:
public void testInterfaces() { ImplementingClassA u = new ImplementingClassA(); ImplementingClassB v = new ImplementingClassB(); InterfaceA w = new ImplementingClassA(); InterfaceA x = new ImplementingClassB(); InterfaceB y = new ImplementingClassA(); InterfaceB z = new ImplementingClassB(); u.interfaceMethodA(); // prints "interfaceA, interfaceMethodA, implementation A" u.interfaceMethodB(); // prints "interfaceB, interfaceMethodB, implementation A" v.interfaceMethodA(); // prints "interfaceA, interfaceMethodA, implementation B" v.interfaceMethodB(); // prints "interfaceB, interfaceMethodB, implementation B" w.interfaceMethodA(); // prints "interfaceA, interfaceMethodA, implementation A" x.interfaceMethodA(); // prints "interfaceA, interfaceMethodA, implementation B" y.interfaceMethodB(); // prints "interfaceB, interfaceMethodB, implementation A" z.interfaceMethodB(); // prints "interfaceB, interfaceMethodB, implementation B" }
但是,你永远无法执行以下操作:
public void testInterfaces() { InterfaceA y = new ImplementingClassA(); InterfaceB z = new ImplementingClassB(); y.interfaceMethodB(); // ERROR! z.interfaceMethodA(); // ERROR! }
你无法执行此操作的原因是这种y类型interfaceA,并且没有interfaceMethodB()in interfaceA。同样,z是类型interfaceB,interfaceMethodA()in 中没有interfaceB。
y
interfaceA
interfaceMethodB()in interfaceA
z
interfaceB,interfaceMethodA()in
interfaceB
前面我提到过,接口只是抽象类的一种特殊形式。为了说明这一点,请看下面的代码。
interface Interface { void abstractMethod(); } abstract public class AbstractClass { abstract public void abstractMethod(); }
你将以几乎完全相同的方式从这些类继承:
public class InheritsFromInterface implements Interface { public void abstractMethod() { System.out.println("abstractMethod()"); } } public class InteritsFromAbstractClass extends AbstractClass { public void abstractMethod() { System.out.println("abstractMethod()"); } }
实际上,你甚至可以像这样更改接口和抽象类:
interface Interface { void abstractMethod(); } abstract public class AbstractClass implements Interface { abstract public void abstractMethod(); } public class InheritsFromInterfaceAndAbstractClass extends AbstractClass implements Interface { public void abstractMethod() { System.out.println("abstractMethod()"); } }
但是,接口和抽象类之间有两个区别。
第一个区别是接口无法实现方法。
interface Interface { public void implementedMethod() { System.out.println("implementedMethod()"); } }
上面的接口会生成编译器错误,因为它具有的实现implementedMethod()。如果你想实现该方法但不能实例化该类,则必须这样做:
abstract public class AbstractClass { public void implementedMethod() { System.out.println("implementedMethod()"); } }
那不是一个抽象类,因为它的成员都不是抽象的,而是合法的Java。
接口和抽象类之间的另一个区别是,一个类可以从多个接口继承,但只能从一个抽象类继承。
abstract public class AbstractClassA { } abstract public class AbstractClassB { } public class InheritsFromTwoAbstractClasses extends AbstractClassA, AbstractClassB { }
上面的代码生成一个编译器错误,不是因为这些类都是空的,而是因为InheritsFromTwoAbstractClasses它试图从两个抽象类继承,这是非法的。以下内容完全合法。
InheritsFromTwoAbstractClasses
interface InterfaceA { } interface InterfaceB { } public class InheritsFromTwoInterfaces implements InterfaceA, InterfaceB { }
接口和抽象类之间的第一个差异是第二个差异的原因。看一下下面的代码。
interface InterfaceA { void method(); } interface InterfaceB { void method(); } public class InheritsFromTwoInterfaces implements InterfaceA, InterfaceB { void method() { System.out.println("method()"); } }
上面的代码没有问题,因为InterfaceA并且InterfaceB没有任何隐藏的东西。很容易看出调用method会打印“ method()”。
InterfaceA
InterfaceB
method
现在看下面的代码:
abstract public class AbstractClassA { void method() { System.out.println("Hello"); } } abstract public class AbstractClassB { void method() { System.out.println("Goodbye"); } } public class InheritsFromTwoAbstractClasses extends AbstractClassA, AbstractClassB { }
这与我们的其他示例完全相同,除了因为我们被允许在抽象类中实现方法而已,并且因为我们不必在继承类中实现已经实现的方法而没有。但是你可能已经注意到,这是一个问题。我们打电话时会new InheritsFromTwoAbstractClasses().method()怎样?是否打印“ Hello”或“再见”?你可能不知道,Java编译器也不知道。另一种语言,C ++允许这种继承,并且它们以通常非常复杂的方式解决了这些问题。为了避免这种麻烦,Java决定将这种“多重继承”定为非法。
new InheritsFromTwoAbstractClasses().method()
Java解决方案的缺点是无法完成以下操作:
abstract public class AbstractClassA { void hi() { System.out.println("Hello"); } } abstract public class AbstractClassB { void bye() { System.out.println("Goodbye"); } } public class InheritsFromTwoAbstractClasses extends AbstractClassA, AbstractClassB { }
AbstractClassA并且AbstractClassB是“ mixins”或不打算实例化的类,但为通过继承“混合到”这些类的功能添加了功能。弄清楚如果调用new InheritsFromTwoAbstractClasses().hi()或会发生什么,显然没有问题new InheritsFromTwoAbstractClasses().bye(),但是你不能这样做,因为Java不允许这样做。
AbstractClassA并且AbstractClassB是“ mixins”
new InheritsFromTwoAbstractClasses().hi()
new InheritsFromTwoAbstractClasses().bye()
(我知道这是一篇很长的文章,所以如果其中有任何错误,请告诉我,我将予以纠正。)