Установка типа поля в суперклассе из подкласса (Java) - PullRequest
1 голос
/ 18 июня 2010

Я пишу проект в Google App Engine, в нем есть несколько абстрактных классов, которые, я надеюсь, я смогу использовать в своих будущих проектах, и ряд конкретных классов, унаследованных от них.Среди других абстрактных классов у меня есть абстрактный сервлет, который управляет пользователями, и у меня есть абстрактный пользователь.AbstractUser имеет все необходимые поля и методы для его хранения в хранилище данных и определения, зарегистрирован ли пользователь в моей службе или нет.Он не реализует какую-либо конкретную функциональность проекта.Абстрактный сервлет, который управляет пользователями, ссылается только на методы, объявленные в классе AbstractUser, что позволяет ему генерировать ссылки для входа, выхода и регистрации (для незарегистрированных пользователей).Для реализации пользовательской функциональности конкретного проекта мне нужно создать подкласс абстрактного пользователя.Все сервлеты, которые я использую в своем проекте, являются косвенными потомками этого абстрактного сервлета управления пользователями, и пользователь является защищенным полем, поэтому сервлеты-потомки могут использовать его как свое собственное поле.Однако всякий раз, когда я хочу получить доступ к какому-либо конкретному методу проекта конкретного пользователя, мне нужно привести его к этому типу.т.е.

(abstract user managing servlet)
...
AbstractUser user = getUser();
...
abstract protected AbstractUser getUser();


(project-specific abstract servlet)
@Override
protected AbstractUser getUser() {
   return MyUserFactory.getUser();
}

любой другой специфичный для проекта сервлет:

int a = ((ConcreteUser) user).getA();

Хорошо, я хотел бы как-то сделать так, чтобы тип «пользователя» в суперклассе зависел от чего-тов специфическом для проекта абстрактном классе.Это вообще возможно?

И я не хочу перемещать все элементы управления пользователями в слой, специфичный для проекта, поскольку я хотел бы, чтобы это было написано для моих будущих проектов:)

Спасибо за вашу помощь.

Ответы [ 2 ]

3 голосов
/ 18 июня 2010

Сделайте ваш AbstractServlet универсальный:

public class AbstractServlet<T extends AbstractUser> { 
    private T user;
    protected abstract T getUser();
    ...

Тогда вы можете заставить реализации использовать определенный подкласс AbstractUser:

public class ConcreteServlet extends AbstractServlet<ConcreteUser> { ...

Тогда вам больше не нужно будетприведение, как и любое место, где у вас есть T в базовом классе, ваша реализация теперь будет ссылаться на ConcreteUser:

@Override
protected abstract ConcreteUser getUser() { .. }
0 голосов
/ 18 июня 2010

Я думаю, что вам нужен общий класс:

class AbstractUserManager<UserType extends AbstractUser> {
    protected UserType user;    

    public UserType getUser() {
        return user;
    }

    public void addUser(UserType u) {
        this.user = u; 
    }

    ...some other methods that use AbstractUser and dont need specific functionality...
}

//Class used for managing AbstractUsers with no extra features
class SimpleUserManager extends AbstractUserManager<AbstractUser> {
//No body as AbstractUserManager is enough
}

//Class that manages CrazyUsers
class CrazyUserManager extends AbstractUserManager<CrazyUser> {
    public CrazyUserManager() {
        this.setUser(new CrazyUser());
    }

    public someNewFunction() {
        this.getUser().someCrazyActionOnlyCrazyUsersHave();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...