Reputation: 3482
The idea is from the SSO class invoke the method login with an instance of MyCredentials. The end results is that MyCredentials will be available in MyAuthentication.
Issue: MyAuthentication creates an error due to the interface expecting an instance of Credentials where I'm attempting to send an instance of MyCredentials. I'm not quite sure what to do at this point.
There are currently several implementation of interface Authentication. I cannot change it. Am I doomed?
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
What happens when an implementation has to deal with both Credentials and MyCredentials?
Should I follow the same as what I did with the Context class and duplicate the method with the different class? Or is there a better way?
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
Even with the two methods with different signatures, it's always the method with Credentials that fires....
Upvotes: 1
Views: 172
Reputation: 197
You're not doomed. The interface looks fine.
I think what you need to do is change the implementation of MyAuthentication. You need a method in there that overrides the method in the interface (with the same exact signature). For example:
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){
...
}
}
Upvotes: 1
Reputation: 279930
Harness the power of generics
interface Authentication<T extends Credentials> {
public User createUser(T c);
}
class MyAuthentication implements Authentication<MyCredentials> {
@Override
public User createUser(MyCredentials c) {
// ...
}
}
The type parameter T
can be Credentials
or any of its sub types. Your implementations will specify one of these. as a type argument.
Upvotes: 4