2013-12-05 8 views
1

Идея из класса SSO вызывает метод login с экземпляром MyCredentials. Конечными результатами является то, что MyCredentials будет доступен в MyAuthentication.Невозможно реализовать унаследованный абстрактный метод

Ошибка: MyAuthentication создает ошибку из-за интерфейса, ожидающего экземпляра учетных данных, где я пытаюсь отправить экземпляр MyCredentials. Я не совсем уверен, что делать в этот момент.

В настоящее время существует несколько вариантов аутентификации интерфейса. Я не могу его изменить. Я обречен?

public class Credentials{ 
    public Credentials(){ 
      ... 
    } 
} 

public class MyCredentials extends Credentials{ 

    public MyCredentials(){ 
     super(); 
     //extend Credentials here 
    } 
} 

public interface Authentication{ 
    public User createUser(Credentials c){ 
     ... 
    } 
} 

public class MyAuthentication implements Authentication{ 

    public User createUser(MyCredentials c){ 
     ... 
    } 
} 

public class Context{ 

    ... 

    //This was there already 
    public login(String login, String password){ 
     Manager.get(new Credentials(login, password)); 
      //at some point, interacts with MyAuthentication 
    } 

    //I added this 
    public login(MyCredentials c){ 
     Manager.get(c); 
      //at some point, interacts with MyAuthentication 
    } 
} 

public class SSO{ 
    Context ctx; 

    public do(){ 
     MyCredentials c = new MyCredentials(); 
     ctx.login(c);  
    } 
} 

Update # 1

Что происходит, когда реализация имеет дело с обоими мандатной и MyCredentials?

Должен ли я следовать тому же, что и я, с классом Context и дублировать метод с другим классом? Или есть лучший способ?

public interface Manager<T extends Credentials> { 

    Repository get(T credentials) throws RepositoryException; 
} 

public class LocalManager implements Manager { 
    public Repository get(final Credentials credentials) throws Exception { 
      AuthenticatedUser user = userAuthenticator.authenticate(credentials); 
      return new RepositoryImpl(commonRepository, user); 
     } 

    //Add this new method? 
    public Repository get(final MyCredentials credentials) throws Exception { 
      AuthenticatedUser user = userAuthenticator.authenticate(credentials); 
      return new RepositoryImpl(commonRepository, user); 
     } 

} 

Update # 2

Даже с этими двумя методами с разными подписями, это всегда метод с учетными данными, пожары ....

+0

Почему вы изменили подпись 'createUser', чтобы использовать тип' MyCredentials' вместо базового типа? – MadConan

+0

@MadConan, потому что я ноб на Java, и мне нужно было передать больше данных, содержащихся в MyCredentials. Насколько мне известно, так и было. – TekiusFanatikus

+0

Это не нужно. Поскольку MyCredentials расширяет учетные данные, он является типом учетных данных. Дженерики - это путь (см. Ответ Сотириоса), но вы также можете просто проверить тип внутри метода, чтобы вам не пришлось менять подпись. – MadConan

ответ

4

Harness сила дженериков

interface Authentication<T extends Credentials> { 
    public User createUser(T c); 
} 


class MyAuthentication implements Authentication<MyCredentials> { 

    @Override 
    public User createUser(MyCredentials c) { 
     // ... 
    } 
} 

Параметр типа T может быть Credentials или любым из его подтипов. В ваших реализациях указывается один из них. как аргумент типа.

+0

Eclipse перестала жаловаться ... нужно скомпилировать и протестировать сейчас. – TekiusFanatikus

+0

просто интересно, можете ли вы прокомментировать мое обновление. По сути, реализация должна иметь дело с двумя типами учетных данных ... есть ли лучший способ, чем копирование существующего метода и просто изменение параметра в MyCredentials? – TekiusFanatikus

+0

@TekiusFanatikus Я посмотрю, когда вернусь домой. –

1

Вы не обречены. Интерфейс выглядит отлично.

Я думаю, что вам нужно изменить реализацию MyAuthentication. Вам нужен метод, который переопределяет метод в интерфейсе (с той же точной подписью). Например:

public class MyAuthentication implements Authentication{ 

    public User createUser(Credentials c) 
    { 
     if(c instancof MyCredentials) 
     { 
     MyCredentials myCredentials = (MyCredentials)c; 
     createUser(myCredentials); 
     } 
     else 
     { 
     throw new RuntimeException("This implementation only handles Credentials of type MyCredentials"); 
     } 
    } 

    public User createUser(MyCredentials c){ 
     ... 
    } 
} 
+1

+1, но предпочтительным является общий подход, предложенный @SotiriosDelimanolis. – Sage

+0

Да, но ОП сказал, что он не может изменить интерфейс. Предлагаемый общий подход предполагает изменение интерфейса. Я думаю, что общий интерфейс представлен красиво, но оригинал можно работать с отличным качеством. – bischoje

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