Java: Как создать функцию, которая может принимать только объект, который является интерфейсом? - PullRequest
0 голосов
/ 19 ноября 2009

Мне нужно написать функцию, которая принимает объект, но я хочу, чтобы при вызове функции (не после вызова функции) объект был интерфейсом.

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

Что я имею в виду?

interface ISomething {...} 
class A implements ISomething { ... }
ISomething something = new A(); 
MyClass.register(something);

В этом примере переданный объект является интерфейсом, и я хочу, чтобы функция MyClass.register применяла это требование в своем объявлении.

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

Ответы [ 7 ]

10 голосов
/ 19 ноября 2009

Чтобы принимать только объекты, которые реализуют интерфейс в качестве аргумента, используйте интерфейс в качестве типа, т. Е .:

void acceptMaps(Map argument) {
}

можно вызывать с объектами, реализующими интерфейс Map, например HashMap, но не с, например, String s, поскольку они не реализуют Map.

Это то, что вы имели в виду под своим вопросом?

Редактировать в этом примере принимаются объекты, реализующие SortedMap, который расширяет Map, поэтому в вашем случае вы можете создать BaseInterface и расширить его в интерфейсах (например, AcceptedInterface extends BaseInterface ) вы хотите, чтобы вас приняли методом .register(BaseInterface arg).

5 голосов
/ 19 ноября 2009

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

Я думаю, вам нужно переосмыслить то, что вы пытаетесь достичь.

4 голосов
/ 19 ноября 2009

Вы проводите различие между типом объекта (в данном случае A) и типом ссылки на объект (в данном случае ISomething).

Похоже, вы хотите разрешить этот код:

ISomething something = new A(); 
MyClass.register(something);

но запретите этот код:

A something = new A(); 
MyClass.register(something);

Не думаю, что этого можно достичь с помощью Java.

1 голос
/ 19 ноября 2009

Дайте мне посмотреть, понимаю ли я.

Вы хотите во время компиляции проверить, что переданный функции аргумент является каким-то интерфейсом? Любой интерфейс?

Если это вопрос, то ответ - ты не можешь.

Я не знаю, какой интерфейс я собираюсь получить [...] Мне нужен настоящий интерфейс.

На самом деле вы не можете проверить, если не знаете, какой тип ожидать.

В Java вам нужно знать тип для проверки параметра, аргумент должен быть того же типа или потомка, Java не делает различий в этом отношении во время компиляции, вы можете сделать это во время выполнения как Дафф ответил.

0 голосов
/ 19 ноября 2009

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

Interface_t x = new Class_which_implements_interface_t();

в отличие от

Class_which_implements_interface_t y = new Class_which_imlements_interface_t();

Единственная проблема в том, что если вы сделаете такую ​​функцию:

void some_func(Interface_t z) {...}

И вы вызываете его с помощью some_func(x); или some_func(y);, функция передает ссылку по значению, что означает, что внутри some_func, z является копией x или y, которая была приведена к Interface_t указатель. Нет способа получить информацию о том, какого типа был оригинальный указатель. Пока он может быть преобразован в Interface_t, он будет компилироваться и запускаться.

0 голосов
/ 19 ноября 2009

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

И невозможно ограничить сигнатуру метода использованием интерфейса, скажем, вы разрешите тип «Животное», но не тип «Собака», который реализует поведение животных. (Я думаю, это то, что вы искали)

В качестве примера - вам нужна ошибка компилятора для этой реализации:

interface ISomething {...} 
class A implements ISomething { ... }
ISomething something = new A(); 
MyClass.register(something);

A unwanted = (A) something;
MyClass.register(unwanted); // <- compilation error here

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

0 голосов
/ 19 ноября 2009

Вы можете спросить класс объекта, который вы получаете, интерфейсы, которые он реализует во время выполнения. Если вы не можете дать компилятору типы ожидаемых интерфейсов, он не сможет предсказать, что будет передаваться в ваш метод, поэтому вам придется использовать отражение во время выполнения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...