Используйте методы, объявленные в реализации, которые не определены в интерфейсе - PullRequest
3 голосов
/ 16 марта 2012

У меня есть класс, определенный интерфейсом

public interface Test {
    void testMethod();
}

Test test = new TestImpl();

public class TestImpl implements Test {
    @Override
    public void testMethod() {
         //Nothing to do here
    }

    public void anotherMethod() {
        //I am adding this method in the implementation only.
    }
}

Как я могу вызвать другой метод?

test.anotherMethod(); //Does not work.

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

Ответы [ 6 ]

6 голосов
/ 16 марта 2012

Проблема со следующей строкой:

Test test = new TestImpl();

Это говорит компилятору забыть, что новый объект является TestImpl, и обрабатывать его как обычный старый Test. Как известно, у Test нет другого метода ().

То, что вы сделали, называется «апкастинг» (приведение объекта к более общему типу). Как сказал другой автор, вы можете решить проблему, не обновляя:

TestImpl test = new TestImpl();

Если вы уверены , что объект Test действительно является TestImpl, вы можете уменьшить его (скажите компилятору, что это более конкретный тип):

Test test = new TestImpl();
:
((TestImpl) test).anotherMethod();

Однако, как правило, это плохая идея, поскольку она может вызвать ClassCastException. Работайте с компилятором, а не против него.

2 голосов
/ 16 марта 2012

Если вы хотите избежать приведения непосредственно к вашему классу реализации, я бы создал другой интерфейс:

public interface SpecificTest extends Test { 
    void anotherMethod();
}

И затем ваш TestImpl реализует этот интерфейс (что означает, что вы можете объявить его как Test или SpecificTest):

SpecificTest test = new TestImpl();
test.anotherMethod();
2 голосов
/ 16 марта 2012

использование

TestImpl test = new TestImpl();

тогда

test.anotherMethod();//It will work now

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

1 голос
/ 16 марта 2012

Конечно, вы можете получить доступ к своим методам, как было сказано выше, но вы должны придерживаться лучших практик в программировании.Поэтому, если вы не можете добавить необходимые методы в Interface1, создайте Interface2, который расширяет Inteface1, и, наконец, добавьте ваши методы.

0 голосов
/ 07 мая 2015

Если вы не хотите вводить тип cast для конкретного класса, вы можете сделать anotherMethod () как закрытый метод и вызывать его внутри testMethod () на основе некоторой логики.

например,

testMethod()
{
   if(foo)
  {
     anotherMethod();
  }
}

Это обходной путь, который можно использовать, если вы не хотите создавать новые методы в дочернем классе, поскольку вы не можете вызывать их, используя ссылку на родительский класс / интерфейс.

0 голосов
/ 16 марта 2012

Вы можете вызвать его, если приведете к реализующему классу, который реализует этот метод. Короче:

Test test = new TestImpl();

// ... and later / somewhere else

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