微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

尝试从父静态类型对象访问子方法时,什么是好方法?

如何解决尝试从父静态类型对象访问子方法时,什么是好方法?

我在继承方面遇到问题。我已经用那些帐户类别进行了说明:

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 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?