2015-04-25 4 views
3

Когда класс реализует интерфейс, делает ли объекты, созданные из класса, воспринимаемыми как объект этого интерфейса?Внедрение интерфейсов и объектов

Т.е., если класс, реализующий интерфейс Runnable, создает экземпляры, созданные из этого класса, для вызова объекта Runnable?

Итак, где ожидаемая ссылочная переменная Runnable (скажем, в параметре метода или конструктора), почему это законно, что мы можем предоставить экземпляр класса в качестве аргумента этому методу или конструктору? Это потому, что, реализуя интерфейс, класс, по сути, является объектом интерфейса?

ответ

5

Объект класса C, который реализует интерфейс I, можно назвать объектом этого интерфейса, хотя один объект может иметь множество интерфейсов. Liskov substitution principle требует C, чтобы можно было использовать в любом месте, где I требуется, так что по сути I становится контрактом из C, представляющей собой подмножество C сек способностей, применительно к конкретной ситуации.

Например, когда объект реализует Runnable, метод run() в интерфейсе представляет собой особый аспект класса в библиотеке классов Java, а именно - что объекты класса могут быть «бежал» (по телефону run() на них) , Наличие Runnable позволяет кодировать логику вашего потока независимо от разработчиков Java, которые пишут свой код выполнения потока независимо от логики вашей реализации.

+0

спасибо. Итак, просто чтобы подтвердить, где интерфейс ожидается как аргумент метода, если конкретный класс реализует интерфейс внутри тела класса, то вы можете передать ключевое слово «this» в качестве аргумента для метода? То есть, это работает только потому, что «это» (что относится к объекту, в котором был вызван метод) ** содержит ** реализованный метод интерфейса? – 151SoBad

+0

@ 151SoBad "[...] вы можете передать ключевое слово' this' в качестве аргумента метода? " Это верно. «это работает только потому, что' this' [...] содержит реализованный метод интерфейса? » Класс может содержать все методы из интерфейса без реализации этого интерфейса (например, потому что автор забыл написать «реализует XyzInterface»). В этом случае наличие всех методов будет недостаточным: нужно объявить класс как реализацию интерфейса, что связано с обещанием реализовать все методы интерфейса. – dasblinkenlight

+0

Отлично, большое спасибо за проницательность. – 151SoBad

2

Ссылка на Runnable возможна, поскольку объект Runnable должен иметь все методы в интерфейсе Runnable.

Таким образом, вы можете получить доступ ко всем этим методам во время выполнения.

Если класс, который называется реализовать Runnable бы как-то не реализовать Runnable - там будет ошибка компиляции, как Java Language Specification 7 chapter 8 (classes) - 8.1.5 (superinterfaces) указывает:

класс называется реализовать все свои суперинтерфейсов.

Пример, приведенный заключается в следующем:

Пример 8.1.5-3. Реализация Методы суперинтерфейсом

interface Colorable { 
    void setColor(int color); 
    int getColor(); 
} 

class Point { int x, y; }; 

class ColoredPoint extends Point implements Colorable { 
    int color; 
} 

Эта программа вызывает ошибка времени компиляции а, потому что ColoredPoint не является абстрактным классом, но не в состоянии обеспечить реализацию методов SetColor и GetColor интерфейса раскрашиваем.

1

Объекты наследуют интерфейсы родительских классов, а методы из этих интерфейсов могут быть переопределены в подклассах.

Значение интерфейсов заключается в том, что они позволяют создавать методы, которые могут вставлять различные классы объектов в качестве входных данных, принимая тип интерфейса в качестве входных данных.

Любой объект, который реализует интерфейс, фактически является «интерфейсом», который может использоваться для данных интерфейсов, которые он реализует.

Реализация интерфейса классом подразумевает способность этого класса выполнять любые методы, указанные в интерфейсе. Таким образом, любой метод, который работает на интерфейсе, может работать на чем-то, реализующем интерфейс.

2

Если класс реализует интерфейс, его можно использовать в любом месте, где может использоваться тип интерфейса. Например, если класс реализует Runnable, то экземпляр этого класса может использоваться везде, где может использоваться Runnable. Это пример полиморфизма.

Например, вот это класс, который реализует Runnable:

public class MyRunner implements Runnable { 
    public void run() {} 
} 

Вы можете использовать MyRunner нравится следующим образом:

MyRunner runner = new MyRunner(); 

// can assign to a field of type "Runnable" without a cast 
Runnable runnable = runner; 

// can pass to methods that take a Runnable 
Executors.newFixedThreadPool(3).execute(runner); 

MyRunner класс называется экземпляром Runnable. Вы даже можете проверить это путем отражения;

public void runIfIsRunnable(Object object) { 
    if (object instanceof Runnable) { 
    Runnable r = (Runnable) object; 
    r.run(); 
    } 
} 

Использование InstanceOf часто считается код запах, но бывают ситуации, когда это полезно, как и при создании экземпляров класса с помощью отражения.

0

Интерфейс устанавливает контракт, согласно которому объект будет содержать методы, определенные в интерфейсе, и этот контракт применяется компилятором. Поэтому компилятор проверяет это.

По соглашению, интерфейсы, заканчивающиеся на «-ий», являются «доступными», чтобы показать это поведение (хотя это отнюдь не является жестким правилом). Но в конце концов, тип объекта является либо java.lang.Object, либо прямым или косвенным его расширением. Если вы посмотрите на дерево наследования на любом Javadoc, вы увидите иерархию классов, расширяющую друг друга и известные классы реализации интерфейсов.

Таким образом, обычно не говорится об объектах, созданных классом как об объектах интерфейса, а о том, что класс реализует.