【问题标题】:Interface with two different implementations与两种不同实现的接口
【发布时间】:2011-08-16 02:42:35
【问题描述】:

我有一个接口Person,我有两个类FemaleMale 实现了该接口。

对于女性类,我有一个方法getPregnancyMonth,而我的男性类没有。将该方法添加到我的接口Person 成为一个问题,因为我的Male 类现在需要从接口继承该方法;但男性永远不会怀孕。

什么是解决方案,我需要extendPerson 而不是implement

编辑:对不起,如果我的问题不清楚。在这种情况下,我将MaleFemale 类中的get/set 方法添加到接口中。

    static void Main(Form form) {
        Person person = Factory.createPerson(form.getGender());
        person.setName(form.getName());

        if ("F".equals(gender)) {
            person.setPregnancyMonth(form.getPregnancyMonth());
        }
    }

我的问题是,由于我的接口有getPregnancyMonth,所以我的男性必须将该方法添加到具体类中以实现接口。有没有办法避免这种情况?

【问题讨论】:

  • 请解决您的问题,这不是工厂模式问题,而是关于继承和OO设计的一般问题。

标签: java oop inheritance


【解决方案1】:

getPregnancyMonth 不应在Person 的界面中。

个人...没有双关语...我认为您应该将Person 创建为一个抽象类,因为女性和男性将共享许多相同的属性和功能。

然后您可以创建反映每个性别的独特功能的女性和男性界面。

【讨论】:

  • 或者您也可以将女性和男性保留为具体类。
【解决方案2】:

应该不需要将该方法移动到Person 接口中。主要技巧是,在执行getPregnancyMonth() 时,您必须确保处理的是Female 实例,而不仅仅是Person 实例。

例如,如果您需要处理一堆不需要任何特殊处理的Person 对象,则可以创建一个方法来轻松完成:

public static void processPeople(List<Person> people) {
    for (Person p : people) {
        p.someMethod();
    }
}

但是,当您必须处理getPregenancyMonth() 方法时,您必须确保您的方法只接受Female 实例:

public static void checkBirthSchedule(Female girl) {
    girl.getPregnancyMonth();
    ...
}

换句话说,当你试图理解时,在更高的接口中尽可能保持抽象,但确保在需要时使用更具体的类型。使用一种技术,例如使用更具体的 Person 类型创建一个单独的方法,可以节省您在编译时获取 ClassCastException 的时间,这非常好。

【讨论】:

    【解决方案3】:

    在我看来,getPregnancyMonth 不够通用,不能用于Person 接口。它可能应该只在女性类中定义。

    您还可以定义包含getPregnancyMonth 的第二个接口。女性将同时实施。

    【讨论】:

    • +1 将与怀孕相关的内容放在关注该行为的界面上
    【解决方案4】:

    不要将getPregnancyMonth 添加到Person。正如您所发现的,这没有多大意义。

    在面向对象的编程中,基类/接口应该(理想情况下)只包含其每个子类共有的细节——因为getPregnancyMonth 对两个子类都不共有(对于Male),它不应该在Person 接口中。我再次强调 - 这是在谈论理想。

    正如其他答案所建议的那样,如果可以的话,尽量完全避免这个问题。例如,您可以使用instanceof 来检测给定的PersonMale 还是Female,并且仅当PersonFemale 时才调用getPregnancyMonth

    编辑,回应评论:使用所描述的工厂方法在很大程度上毫无意义。如果我们忽略那些不希望被贴上“正常”性别标签的人,那么您将永远只创建一个 MaleFemale 对象 - 你最好拥有 public static Female createFemale ( ) 和 @987654336 @ 方法在您的 Factory 中。这样,您将避免所有您一直遇到的这些麻烦。它还将摆脱像枚举一样使用的字符串(即“男性”或“女性”作为getPerson 的参数),但这是完全不同的事情......

    如果您仍想使用组合工厂方法,可以将结果转换为Female

    Female female = (Female) Factory.getPerson("female");
    female.getPregnancyMonth ( );
    

    或者,如果您有一个 Person 可能是也可能不是 Female,您也可以投射:

    if (person instanceof Female)
    {
        Female female = (Female) person;
    
        female.getPregnancyMonth( );
    }
    

    虽然我不能说我过于喜欢这两种方法中的任何一种 - 它们各有千秋,但通常有更好的方法。

    【讨论】:

    • 但它不会让我编译,因为当 Person female = Factory.getPerson("female") 时,方法 female.getPregnancyMonth() 将不存在,因为 Person 没有该方法
    【解决方案5】:

    实施/扩展在这里并不重要。您可以让 isPregnant() 始终为男性返回 false,或者您可以直接将该方法推送到女性中。看到您认为男性怀孕是荒谬的,您将设计您的代码,使其仅在女性上调用 isPregnant(),而不仅仅是对任何人。

    顺便说一句,我并不是说要加入一个 if(person instanceof Female),而是设计你的 heiarchy 以避免这种情况。

    【讨论】:

      【解决方案6】:

      这听起来像是一个损坏的对象层次结构,但按照说明,您的界面需要两个方法:isFemale() 和 getPregnancyMonth()。然后 Male.getPregnancyMonth() 抛出 UnsupportedOperationException。更好的方法可能是设计您的模型,以便永远不会将男性置于询问其怀孕月份的位置。

      【讨论】:

        猜你喜欢
        • 2019-07-31
        • 2018-10-03
        • 1970-01-01
        • 2018-02-27
        • 2013-07-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多