具有两个不同实现的接口

7
我有一个接口 Person,另外还有两个类 FemaleMale 实现了这个接口。
对于 Female 类,我添加了一个方法 getPregnancyMonth,而 Male 类没有该方法。将该方法添加到接口 Person 中会出现问题,因为我的 Male 类现在要从接口继承该方法;但是男性永远不会怀孕。
有什么解决办法吗?我需要使用extend 来替代 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方法,所以我的男性需要在具体类中添加该方法来实现接口。是否有避免这种情况的方法?


请修正您的问题,这不是工厂模式的问题,而是关于继承和面向对象设计的一般性问题。 - Angel O'Sphere
6个回答

5

getPregnancyMonth 不应该出现在 Person 接口中。

个人认为,你应该将 Person 创建为一个抽象类,因为男性和女性将共享许多相同的属性和功能。

然后,你可以创建反映每个性别独特功能的 Female 和 Male 接口。


或者你也可以将“女性”和“男性”保留为具体类。 - Logan

3
不需要将该方法移入“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,这非常好。

2

我认为getPregnancyMonth不够通用,不能在Person接口中使用。它应该只在Female类中定义。

你也可以定义第二个接口来包含getPregnancyMonth,然后Female实现这两个接口。


+1 在一个专注于该行为的界面上放置与怀孕相关的事物 - Crowie

1

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

在面向对象编程中,基类/接口应该(理想情况下)只包含每个子类共有的细节 - 由于getPregnancyMonth不适用于两个子类(对于Male来说没有任何意义),因此它不应该出现在Person接口中。再次强调 - 这是讨论理想情况。

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

编辑,针对评论的回应:按照上述描述使用工厂方法大多是没有意义的。如果忽略那些不希望被标记为“正常”性别的人,你只会创建一个男性(Male)或者女性(Female)对象——最好在工厂(Factory)中只有public static Female createFemale ( )public static Male createMale ( )方法。这样,你将避免所有这些麻烦。它还可以消除像枚举一样使用字符串(即作为getPerson的参数的“male”或“female”),但这是完全不同的问题...

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

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

或者,如果你有一个可能是或可能不是女性Person,你也可以进行强制类型转换:

if (person instanceof Female)
{
    Female female = (Female) person;

    female.getPregnancyMonth( );
}

虽然这两种方法都有其适用的场合,但我并不是特别喜欢它们,通常还有更好的方法。


但是它不允许我编译,因为当Person female = Factory.getPerson("female")时,方法female.getPregnancyMonth()将不存在,因为Person没有该方法。 - gathcea

1

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

顺便说一下,我并不是指随意加入if(person instanceof Female),而是设计您的层次结构以避免这种情况。


0

听起来像是一个破碎的对象层次结构,但按照所述方式,您的接口需要两个方法:isFemale()和getPregnancyMonth()。然后Male.getPregnancyMonth()会抛出UnsupportedOperationException异常。更好的方法可能是设计您的模型,使得男性永远不会被置于需要询问其怀孕月份的位置。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接