如何解决尝试从父静态类型对象访问子方法时,什么是好方法?
我在继承方面遇到问题。我已经用那些帐户类别进行了说明:
class Account {
accountLevel = BASIC;
connect() {...}
changePassword() { ... }
ChangeEmail() { ... }
}
class CustomerAccount extends Account {
accountLevel = CUSTOMER;
createOrder() { ... }
payOrder() { ... }
}
class AdminAccount extends Account {
accountLevel = ADMIN;
addProduct() { ... }
deleteProduct() { ... }
}
如果我有一个Account实例,并且想要将其强制转换为AdminAccount来执行addProduct(),那么可以这样做:
Account account = new AdminAccount();
if(account.accountLevel == ADMIN){
AdminAccount adminAccount = (AdminAccount) account;
adminAccount.addProduct();
}
编辑: 我希望所有帐户都在同一列表中,因为它们都使用相同的connect方法。但是当连接帐户时,我仍然有一个帐户对象,但是我想使用它们的动态类型方法,因此我不得不强制转换该对象。
这几乎像instanceof
,但有额外的步骤。我觉得必须强制转换帐户不是OOP,还有其他更优雅的解决方案吗?也许不使用帐户类之间的继承?
解决方法
一种解决方法是:
AdminAccount account = new AdminAccount();
account.addProduct();
如果期望只有管理员帐户可以添加产品,则相关方法应期望输入中包含管理员帐户而不是帐户。将实例创建为帐户而不是管理员帐户是否有原因?
编辑-将样例包装类型处理包括到经理类中。
public static void main(String args[])
{
AccountManager manager = new AccountManager();
manager.addAccount(new User());
manager.addAccount(new User());
manager.addAccount(new Admin());
System.out.println(manager.getUsers().collect(Collectors.toList()));
}
public static final class AccountManager
{
private final List<Account> allAccounts = new ArrayList<>();
public Stream<User> getUsers(){ return getAccountType(User.class); }
public Stream<Admin> getAdmins(){ return getAccountType(Admin.class); }
public Stream<Account> getAccounts(){ return getAccountType(Account.class); }
public <T extends Account> void addAccount(T account) { if(account.connect()) allAccounts.add(account); }
@SuppressWarnings("unchecked") private <T> Stream<T> getAccountType(Class<T> type){ return allAccounts.stream().filter(type::isInstance).map(act -> (T) act); }
}
public static final class User extends Account{}
public static final class Admin extends Account{}
public static class Account { boolean connect(){ return true; } }
,
真的很好。我们称其为OOP中的多态性。父母可以向所有孩子投降。
,通常,通过某种类型属性或if
检查来拥有instanceof
条语句被认为不是一个好习惯。
visitor pattern是替代方法。这是您可以做什么的示意图:
interface IAccount {
void process(AccountProcessor processor);
}
interface AccountProcessor {
void processBasicAccount(Account acc);
void processCustomerAccount(CustomerAccount acc);
void processAdminAccount(AdminAccount acc);
}
这个想法是,您有一个为所有帐户定义process
方法的接口,该接口接收一个AccountProcessor
(您可以在此处更改名称,这只是为了显示示例)。每种不同类型的帐户都应该有一种方法。您甚至可以使用方法重载,即所有方法都可以命名为processAccount
之类的名称,并且可以接收特殊的帐户类型。
现在,您的Account
类及其所有子类型应该实现IAccount
接口:
class Account implements IAccount {
@Override
void process(AccountProcessor processor) {
processor.processBasicAccount(this);
}
// all the other Account stuff
}
class CustomerAccount implements IAccount {
@Override
void process(AccountProcessor processor) {
processor.processCustomerAccount(this);
}
// all the other CustomerAccount stuff
}
class AdminAccount implements IAccount {
@Override
void process(AccountProcessor processor) {
processor.processAdminAccount(this);
}
// all the other AdminAccount stuff
}
现在,所有这些部分都准备就绪,您就可以处理帐户列表了:
class AccountProcessorImpl implements AccountProcessor {
private List<Account> accounts; // filled with all the accounts
void doSomethingWithAllTheAccounts() {
// iterate all the accounts and process each one of them
accounts.forEach(IAccount::process);
}
@Override
public void processBasicAccount(Account acc) {
// do something with the basic account
}
@Override
public void processCustomerAccount(CustomerAccount acc) {
// do something with the customer account
}
@Override
public void processAdminAccount(AdminAccount acc) {
// do something with the admin account
}
}
希望您能掌握总体思路。这只是向您展示核心技术的草图。可能会有变体,例如,您可能为每种不同类型的帐户使用不同的处理器,或者您可以处理AccountProcessorImpl
以外的类中的帐户列表,等等。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。