2012-03-16 2 views
2

У меня есть класс, определенный с помощью интерфейсаИспользовать методы, объявленные в реализации, которые не определены в интерфейсе

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. 
    } 
} 

Как я могу позвонить anotherMethod?

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

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

ответ

5

Проблемы с помощью следующей строки:

Test test = new TestImpl(); 

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

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

TestImpl test = new TestImpl(); 

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

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

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

2

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

TestImpl test = new TestImpl(); 

затем

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

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

0

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

Test test = new TestImpl(); 

// ... and later/somewhere else 

((TestImpl) test).anotherMethod(); 
0

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

+1

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

+0

Да, я согласен с вами, но проблема заключается в возможности получить доступ к ** жирным ** различным ** жирным ** реализациям через интерфейс. Поэтому вы должны помнить о наследовании. – Artemis

2

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

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

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

SpecificTest test = new TestImpl(); 
test.anotherMethod(); 
0

Если вы не хотите типовой брось к конкретному классу, то вы могли бы сделать anotherMethod(), как частный метод и вызвать его в TestMethod() на основе некоторой логики.

например.

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

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

Смежные вопросы