Java继承和避免不断使用instanceof
我有三个类,一个抽象的 User 和两个特定的:NormalUser 持有一个或多个可以不同的 Address 对象的 ArrayList(国内、国际、自定义等),然后是 Admin 类,它有一个返回 true 的方法。它们都包含更多彼此无关的方法。
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");
并说我想在 NormalUser 中使用 addAddress 方法,那么我必须将 users 中的特定用户向下转换为 NormalUser,然后才能在 NormalUser 中使用 addAddress 方法,例如这个:
if (user instanceof NormalUser){
NormalUser normal = (NormalUser) user;
normal.addAddress(...)
}
我希望 NormalUser 和 Admin 都成为 User 的原因是这样我可以在登录时一起处理它们。
我想将 addEmail 添加到 User 类,然后在 NormalUser 类中覆盖它,但我会必须对 NormalUser 类中的每个方法执行此操作,此外,当不需要该功能时,Admin 也会从 User 继承它。
问题1:有没有更好的方法来做到这一点,因为我听说使用instanceof是一件坏事?每次使用特定于 NormalUser 类的方法时,我都必须使用 instanceof。
问题 2:对象地址的 ArrayList 是将 RegularUser 链接到特定地址/(对象)的最佳方式吗?
目前还没有涉及数据库。
例如,用户 a 有 2 个地址,一个国内地址,一个国际地址,用户 b 只有一个国内地址,用户 c 有一个国内地址和一个自定义地址等。
谢谢。
附言。我已经广泛搜索了以前的帖子,但尚未找到解决方案。在我的两本 Java 书中,它们都展示了使用 instanceof 的示例,但没有提到这是一种不好的做法。
I have three classes, an abstract User and two specific: NormalUser which holds an ArrayList of one or more Address objects which can be different (domestic, international, custom etc.) and then the Admin class which has a method which returns true . They both contain more methods which are unrelated to each other.
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;
}
}
Now in another class if I make 4 user objects like this for example:
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");
And say I want to use the addAddress method in NormalUser, then I have to downcast the specfic user in users to NormalUser, before I can use the addAddress method in NormalUser like this:
if (user instanceof NormalUser){
NormalUser normal = (NormalUser) user;
normal.addAddress(...)
}
The reason why I would like both NormalUser and Admin to be a User is so I can process them together when logging in.
I thought of adding the addEmail to the User class and then overriding it in the NormalUser class, but I would have to do that for every method in the NormalUser class, plus Admin would inherit it from the User as well, when it doesnt need that functionality.
Question 1: Is there a better way to do this as I heard using instanceof is a bad thing? and I would have to use instanceof every time I use a method that is specific to the NormalUser class.
Quesiton 2: Is an ArrayList of object Addresses the best way to link the RegularUser to specific addresses/(Objects)?
There is no database involved right now.
So for example user a has 2 addresses one domestic and one international, and user b just has a domestic address, user c has a domestic and a custom address etc.
Thanks.
PS. I've searched the previous posts extensively but havent found a solution. In both my Java books they both show examples of using instanceof but no mention of it being a bad practice.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以使用 访客模式 - 有点笨拙且有点难以阅读,但可能是最适合您的解决方案问题。
实际上,将
addEmail
推送到基类的解决方案并没有那么糟糕。只需在基本User
中提供一个空实现并在RegularUser
中覆盖即可。如果您想检查给定的User
实例是否支持添加电子邮件,请提供另一种方法,例如supportsAddEmail
默认返回false
和true
当覆盖addEmail
时。You can use the Visitor pattern - a bit clumsy and slightly unreadable, but probably the best solution for your problem.
Actually your solution with pushing
addEmail
to base class isn't that bad. Simply provide an empty implementation in baseUser
and override inRegularUser
. If you want to check whether givenUser
instance supports adding e-mails, provide another method likesupportsAddEmail
returningfalse
by default andtrue
when overridingaddEmail
.我认为最简单的解决方案是创建一个 UserList 类,其中包含 NormalUser 列表和 Admin 列表。 UserList 类的实例将替换原始列表。 UserList 类可以提供一些方法,例如:
User getUser(index i) // 使用两个列表实现
User removeUser(index i) // 使用两个列表实现
用于处理适当列表的所有代码都将封装在 UserList 类中。您可以拥有使用两个列表或仅使用一个列表的方法,具体取决于您需要对用户执行的操作。与 UserList 交互的类不知道 UserList 内是否只有一个或两个列表。
I think that the easiest solution is to create a class UserList that would contain a list of NormalUser and a list of Admin. An instance of the class UserList would replace the original list. The class UserList could provide some methods such as:
User getUser(index i) // implemented with the two lists
User removeUser(index i) // implemented with the two lists
All the code for handling the appropriate lists would be encapsulated in the UserList class. You could have methods that use both lists or only one list, depending on what you need to do with the users. Classes that interact with UserList would not know if there is only a single or two lists inside UserList.