Какова хорошая практика для получения правильного возвращаемого класса с наследованием?

#java #oop #inheritance #design-patterns #polymorphism

#java #ооп #наследование #шаблоны проектирования #полиморфизм

Вопрос:

У меня разные типы пользователей, все они наследуют от родительского класса User:

 class User(string username, string password){...}

class UserAdmin(string username, string password) extends User{
   ...
   // new methods
}

class User(string username, string password) extends User{
   ...
   // new methods
}
  

У меня есть метод для входа в систему, но дело в том, что если я войду в систему с учетными данными администратора пользователя, я хочу вернуть администратора пользователя, то же самое для всех других дочерних классов User .

 public User login(String userName, String password) {
    for (User user : usersList) {
        if (user.isCorrectLogin(userName, password)) {
            return user;
        }
    }
    throw new RuntimeException("Login failed !");
}
  

Как я могу это сделать? Должен ли я иметь несколько методов login() для каждого типа пользователей? Или есть другой способ настроить пользователей так, чтобы у них не было этой проблемы в первую очередь?

Ответ №1:

Единый метод входа в систему должен быть подходящим для вашего варианта использования, хотя то, что вы должны сделать, это убедиться, что правильный тип User уже usersList введен. Например:

 List<User> usersList = new ArrayList<>();
usersList.add(new User("steve", "some_secret_password"));
usersList.add(new UserAdmin("bob", "some_even_more_secret_password"));
  

Таким образом, ваш существующий login метод автоматически вернет правильный тип.

Если вы хотите проверить, относится ли возвращаемое значение к определенному типу, вы можете использовать instanceof оператор:

 User user = login(username, password);
if (user instanceof UserAdmin) {
  // Do privileged action
}
  

Однако есть несколько других способов сделать это. Вы могли бы просто заставить каждый конкретный тип пользователя возвращать набор ролей, которые у него есть, таким образом, вы можете instanceof вообще избежать:

 // User
public Set<String> getRoles() {
  return Set.of("user");
}

// UserAdmin
public Set<String> getRoles() {
  return Set.of("user", "admin");
}
  

Тогда ваша логика может стать:

 User user = login(username, password);
if (user.getRoles().contains("admin")) {
  // Privileged action
}
  

Комментарии:

1. Хорошо, но если я хочу иметь эти привилегированные действия внутри своих пользовательских классов, как я могу это сделать?

2. После выполнения instanceof проверки вы можете привести ссылку к нужному типу. UserAdmin admin = (UserAdmin) user;