EchtFettigerKeks
EchtFettigerKeks

Reputation: 1893

Avoid type casting for subclasses

I have two classes that inherit from the same class:

ClientUserManager extends UserManager

and

ServerUserManager extends UserManager

UserManager is abstract.

public abstract class UserManager {

    protected final UserService userService;

    public UserManager(UserService userService) {
        this.userService = userService;
    }

As an example, the server subclass:

public class ServerUserManager extends UserManager {

    public ServerUserManager(UserService userService) {
        super(userService);
    }

    public void someMethod() {
        ((ServerUserSerivice)userService).doSomethingForSERVERONLY();
    }

However, my sub-classes should each be able to use their specializations of UserService (ClientUserService or ServerUserService), as you can already see from someMethod(). I would like to be able to do without the constant typecasting.

Is there a more elegant or generic solution?

Side info: To justify why I want to both generalize things and keep specializations at the same time (as Oğuzhan Aslan already pointed out), let me say that I use a dependency injection framework (Dagger 2) which gives me for the same "key"/superclass, the respective implementation in return (here client or server).

Upvotes: 0

Views: 232

Answers (2)

Michael Poirier
Michael Poirier

Reputation: 21

One option is to use generics:

public abstract class UserManager<T extends UserService> {

    protected final T userService;

    public UserManager(T userService) {
        this.userService = userService;
    }
}

public class ServerUserManager extends UserManager<ServerUserService> {

    public ServerUserManager(ServerUserService userService) {
        super(userService);
    }

    public void someMethod() {
        userService.doSomethingForSERVERONLY();
    }
}

Upvotes: 2

Tal Joffe
Tal Joffe

Reputation: 5828

I'm not entirely clear what you are trying to achieve but I will suggest in general to try and use design patterns according to your use case.

This one seems similar to a "Strategy Pattern". You have a context (UserManager) that should get some specific strategy (UserService) and use it.

For example:

public interface UserService {    
    public void execute(); 
}

public class ServerUserService implements UserService {
    public void execute(){
       //does something for server    
    }; 
}

class ServerUserManager {
    private UserService userService;
 
    public ServerUserManager(UserService userService) {
        this.userService = userService;
    }
 
    public void doSomething() {
        return this.userService.execute();
    }
};

You can google "Strategy Pattern" to see different flavours of implementation

Upvotes: 1

Related Questions