【问题标题】:I need multiple inheritance but I'm using Java我需要多重继承,但我使用的是 Java
【发布时间】:2019-07-04 11:09:42
【问题描述】:

我想为一个简单的商家网站建模,其中包含一个访问者、一个帐户、一个客户和一个管理员。

访客可以有一个篮子。

如果访问者创建或提供凭据,则访问者可以成为客户。

客户和管理员是具有凭据的帐户。

class Account {
    Credentials credentials;
    void logout();
    // other account management methods
}

class Admin extends Account {
}

class Visitor {
    Basket basket;
    // basket management methods
}

class Customer extends Visitor, Account {
    // needs a basket and credentials
}

我尝试了一个 Account 接口,但必须在 Customer 和 Admin 中实现帐户管理方法,我不想重复该代码。我看到 Java 8 中存在接口方法的默认实现。但是如果没有这种 hack,还有其他方法可以实现吗?

【问题讨论】:

  • Java 没有多重继承。
  • 客户不是帐户。不过,客户可能有一个帐户。
  • 您可能需要考虑构图(可能带有装饰)。根据需要或直接从访问者和帐户实例返回字段。恕我直言,继承/定制并不适合聚合。我已经这样做了很多次了,但它通常会变得一团糟。
  • 一般来说,你应该prefer composition over inheritance。继承只是代码重用的一种机制,可以说它不是一个很好的机制。还有其他重用代码的方法,通常是通过创建更多对象来表示事物的可重用部分。 (除了实现继承还有API继承,它在Java中是使用接口实现的。只要你的对象满足这些接口的约定,你就可以并且通常应该实现多个接口.)
  • 用更简单的话来回答 Josh 的回答,维护一个将权限级别返回到 Account(或它可以访问的内容,例如 canDeleteAccountgetPermissions)的方法,并让子类修改它为了允许您围绕它定义更高级别的行为。此外,这甚至可能导致消除具体的 Administrator/Customer 类,并为您提供任何形式的用户的抽象

标签: java multiple-inheritance


【解决方案1】:

您必须重新考虑设计并支持组合而不是继承。 一个简单的规则 - 如何确定是否应该使用一个或另一个:继承是否回答了 "is-a""has-a" 问题?

是客户和帐户吗?不是。客户是可能拥有和帐户的用户。

客户是访客吗?是的,他可能是。

因此,您应该从访客扩展您的客户并添加一个帐户作为该类的成员。

class Account {
    Credentials credentials;
    void logout();
    // other account management methods
}

class Admin {
     private Account account; // + Getters and setters
}

class Visitor {
    Basket basket;
    // basket management methods
}

class Customer extends Visitor {
    private Account account; // + Getters and setters
}

您可以添加一个接口以使其在SOLID方面变得更好:

interface Authenticable {
    Account getAccount();
    Account setAccount(Account account);
}

并让您的客户和管理员实施它

class Customer extends Visitor implements Authenticable {
    private Account account; 
    @Override
    Account getAccount(){return account};
    @Override
    Account setAccount(Account account){this.account = account};
}

如果您仍想避免重复 Account getter 和 setter - 只需从 Customer 扩展 Admin 并覆盖 getBasket() - thow NotImplementedException()

【讨论】:

  • 正确的Authenticable 接口不会提供对帐户的直接访问,而是提供对帐户的操作,Account 本身仍封装在实现中。
  • 汤姆可能是对的。在这种情况下,应在 Utility 方法中实施 Account 操作以避免重复。
  • 不仅可以复制,还可以保护Account 实例中存储的信息,例如凭据。将其提供给其他类可能会导致安全漏洞。
  • 即使在数据库中也不应存储已打开的凭据。它们应该被加密。但你是对的,无论如何这可能是个问题。
【解决方案2】:

你可能需要一个抽象方法来构建类

【讨论】:

    【解决方案3】:

    Java 没有像 python 那样的多重继承。这是事实。

    您可以将Account 从类更改为接口。并创建一个名为“AccountImpl”的类,该类实现Account 接口。在每个要定义帐户管理方法(如AdminCustomer)的类中,您必须有一个Account 接口字段并使用AccountImpl 类对其进行初始化。像这样:

    interface Account { // account management methods } 
    
    class AccountImpl implements Account {
    //implement account interface methods
    }
    
    class Admin {
        Account account;
        public Admin() {
           account = new AccountImpl();
    }
    
    class Customers extends Visitor {
        Account account;
        public Customers() {
           account = new AccountImpl();
    }
    

    例如,如果你想退出,你必须说 `customer.getAccount().logOut();

    这是一种很好的做法,因为您不会重复 Account 的实现,而且将来您可能希望在某些凭据之间做出尊重。这样,您只需创建新的AccountImpl 类。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-07-12
      • 1970-01-01
      • 2012-04-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-26
      相关资源
      最近更新 更多