Наследование Java и избегание постоянного использования instanceof - PullRequest
5 голосов
/ 04 декабря 2011

У меня есть три класса, абстрактный Пользователь и два конкретных: NormalUser, который содержит ArrayList одного или нескольких объектов Address, которые могут быть разными (внутренние, международные, пользовательские и т. Д.), А затем класс Admin, у которого есть метод, который возвращает правда . Они оба содержат больше методов, которые не связаны друг с другом.

abstract class User{
    public User(String username, String pw){
 ...

}

public class NormalUser extends User{
...
    private ArrayList<Address> addresses;

...

    public void addAdress(ArrayList<Address> address){
        addresses.addAll(address);
}

public class Admin extends User{

...
    public boolean getIsAdmin(){
        return true;
  }
}

Теперь в другом классе, если я сделаю 4 пользовательских объекта, например, это:

    ArrayList<User> users;

    users.add(new NormalUser( "1", "pw");
    users.add(new NormalUser( "2", "pw");
    users.add(new NormalUser( "3", "pw");
    users.add(new NormalUser( "4", "pw");
    users.add(new Admin("5", "pw"));
    users.add(new NormalUser( "6", "pw");

И, скажем, я хочу использовать метод addAddress в NormalUser, а затем я вынужден понижать специфицированного пользователя в пользователях до NormalUser, прежде чем я смогу использовать метод addAddress в NormalUser следующим образом:

     if (user instanceof NormalUser){
        NormalUser normal = (NormalUser) user;
        normal.addAddress(...)
        }

Причина, по которой я бы хотел, чтобы и NormalUser, и Admin были пользователями, заключается в том, что я могу обрабатывать их вместе при входе в систему.

Я думал добавить addEmail в класс User и затем переопределить его в классе NormalUser, но я должен был бы сделать это для каждого метода в классе NormalUser, плюс Admin также наследовал бы его от User, когда он эта функциональность не нужна.

Вопрос 1 : Есть ли лучший способ сделать это, как я слышал, использование instanceof - это плохо? и мне придется использовать instanceof каждый раз, когда я использую метод, специфичный для класса NormalUser.

Quesiton 2 : Является ли ArrayList объекта Addresses лучшим способом связать RegularUser с конкретными адресами / (объектами)?

В данный момент база данных не задействована.

Так, например, пользователь a имеет 2 адреса: один внутренний и один международный, а пользователь b просто имеет внутренний адрес, пользователь c имеет внутренний и настраиваемый адрес и т. Д.

Спасибо.

PS. Я много раз искал предыдущие посты, но не нашел решения. В обеих моих книгах по Java они показывают примеры использования instanceof, но не упоминают, что это плохая практика.

Ответы [ 2 ]

3 голосов
/ 04 декабря 2011

Вы можете использовать Шаблон посетителя - немного неуклюжий и немного нечитаемый, но, вероятно, лучшее решение для вашей проблемы.

На самом деле ваше решение с нажатием addEmail на базовый класс не являетсяне так уж и плохо.Просто предоставьте пустую реализацию в базе User и переопределите в RegularUser.Если вы хотите проверить, поддерживает ли данный экземпляр User добавление сообщений электронной почты, укажите другой метод, например supportsAddEmail, возвращающий false по умолчанию и true при переопределении addEmail.

0 голосов
/ 04 декабря 2011

Я думаю, что самым простым решением является создание класса UserList, который будет содержать список NormalUser и список Admin.Экземпляр класса UserList заменит исходный список.Класс UserList может предоставлять некоторые методы, такие как:

  • User getUser (index i) // реализован с двумя списками

  • User removeUser (index i) // реализовано с двумя списками

  • NormalUser getNormalUser (index i) // реализовано с обычным списком пользователей
  • NormalUser removeNormalUser (index i) // реализовано собычный список пользователей
  • Admin getAdmin (index i) // реализован с использованием списка пользователей admin
  • Admin removeAdmin (index i) // реализован с использованием списка пользователей admin
  • ....

Весь код для обработки соответствующих списков будет инкапсулирован в классе UserList.У вас могут быть методы, которые используют оба списка или только один список, в зависимости от того, что вам нужно делать с пользователями.Классы, взаимодействующие с UserList, не будут знать, есть ли в UserList только один или два списка.

...