Интерфейс - это особая форма абстрактного класса, которая не реализует никаких методов. В 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
, и в interfaceA
нет interfaceMethodB()
. Аналогично, z
имеет тип interfaceB
и interfaceMethodA()
в 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
пытается наследовать от двух абстрактных классов, что недопустимо. Следующее абсолютно законно.
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 ()».
Теперь посмотрите на следующий код:
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()
? Это печатает "Привет" или "До свидания"? Вы, вероятно, не знаете, как и Java-компилятор. Другой язык, C ++, допускал такое наследование, и они решали эти проблемы часто очень сложными способами. Чтобы избежать такого рода проблем, Java решила сделать это «множественное наследование» незаконным.
Недостаток решения 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
являются «миксинами» или классами, которые не предназначены для создания экземпляров, но добавляют функциональность к классам, в которые они «смешиваются» посредством наследования. Очевидно, нет проблем с выяснением того, что произойдет, если вы позвоните new InheritsFromTwoAbstractClasses().hi()
или new InheritsFromTwoAbstractClasses().bye()
, но вы не можете этого сделать, потому что Java не позволяет этого.
(я знаю, что это длинный пост, поэтому, если в нем есть ошибки, пожалуйста, дайте мне знать, и я исправлю их.)