简体   繁体   English

与两种不同实现的接口

[英]Interface with two different implementations

I have an interface Person and I have 2 classes Female and Male that implement the interface.我有一个Person接口,我有 2 个实现该接口的类FemaleMale

For the Female class, I have a method getPregnancyMonth that my Male class does not have.对于女性 class,我有一个方法getPregnancyMonth ,而我的男性 class 没有。 Adding that method to my interface Person becomes a problem as my Male class now needs to inherit that method from the interface;将该方法添加到我的接口Person成为一个问题,因为我的Male class 现在需要从接口继承该方法; but the male would never be pregnant.但男性永远不会怀孕。

What would be a solution, do I need to extend Person instead of implement ?什么是解决方案,我是否需要extend Person 而不是implement

EDIT: Sorry if my question wasn't clear.编辑:对不起,如果我的问题不清楚。 In this case I have added both get / set methods from the Male and Female classes to the interface.在这种情况下,我已将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());
        }
    }

My question is, since my interface has getPregnancyMonth , my male has to add that method to the concrete class to implement the interface.我的问题是,由于我的接口有getPregnancyMonth ,我的男性必须将该方法添加到具体的 class 以实现接口。 Is there a way to avoid this?有没有办法避免这种情况?

getPregnancyMonth Should not be in the interface of Person . getPregnancyMonth不应该在Person的接口中。

Personally...no pun intended...I think you should create Person as an abstract class as female and male will share a lot of the same attributes and functions.就个人而言...没有双关语...我认为您应该将Person创建为抽象 class ,因为女性和男性将共享许多相同的属性和功能。

Then you could create Female and Male interfaces that reflect unique functionality for each sex.然后,您可以创建反映每种性别的独特功能的女性和男性界面。

There should be no need to move that method into the Person interface.不需要将该方法移到Person接口中。 The main trick is that when it comes time to execute the getPregnancyMonth() you must ensure you're dealing with a Female instance instead of just a Person instance.主要技巧是,当执行getPregnancyMonth()时,您必须确保处理的是Female实例,而不仅仅是Person实例。

For example, if you need to process a bunch of Person objects that do not require any particular treatment, a method can be created to do so easily:例如,如果您需要处理一堆不需要任何特殊处理的Person对象,可以创建一个方法来轻松完成此操作:

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

However, when you must deal with the getPregenancyMonth() method, you must ensure that your method only accepts Female instances:但是,当您必须处理getPregenancyMonth()方法时,您必须确保您的方法只接受Female实例:

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

In other words, as you are trying to get at, keep things as abstract as you can in higher up interfaces, but ensure you go to a more concrete type when needed.换句话说,正如您试图理解的那样,在更高的接口中尽可能保持抽象,但在需要时确保您使用更具体的类型。 Using a technique like making a separate method with a more specific type of Person saves you at compile time from getting ClassCastException 's, which is very nice.使用一种技术,例如使用更具体的Person类型创建一个单独的方法,可以在编译时节省您获取ClassCastException的时间,这非常好。

In my opinion, getPregnancyMonth is not generic enough to be in a Person interface.在我看来, getPregnancyMonth不够通用,不能放在Person接口中。 It should probably be defined in the Female class only.它可能应该只在女性 class 中定义。

You may also define a second interface containing that getPregnancyMonth .您还可以定义包含该getPregnancyMonth的第二个接口。 Female will implement both.女性将同时实施。

Implement/Extend doesn't really matter here.实施/扩展在这里并不重要。 You can either have isPregnant() always return false for Male, or you can just push the method directly into Female.您可以让 isPregnant() 始终为男性返回 false,或者您可以直接将该方法推送到女性中。 Seeing as you think it is ridiculous that a Male would be pregnant, you would design your code such that it only calls isPregnant() on a Female, not just any person.看到您认为男性怀孕是荒谬的,您将设计您的代码,使其仅在女性上调用 isPregnant(),而不仅仅是对任何人。

BTW By this I don't mean throw in an if(person instanceof Female), design your heiarchy as to avoid this.顺便说一句,我并不是说加入 if(person instanceof Female),设计你的 heiarchy 以避免这种情况。

Don't add getPregnancyMonth to Person .不要将getPregnancyMonth添加到Person As you've discovered, that does not make much sense.正如您所发现的,这没有多大意义。

In object oriented programming, a base class/interface should (ideally) only contain the details that are common to each of its subclasses - since getPregnancyMonth is not common to both subclasses (it doesn't make any sense for a Male ), it shouldn't be in the Person interface.在面向 object 的编程中,基类/接口应该(理想情况下)只包含其每个子类共有的细节 - 因为getPregnancyMonth对两个子类都不共有(它对Male没有任何意义),它应该'不在Person界面中。 Again I stress - this is talking about ideals.我再次强调——这是在谈论理想。

As other answers have suggested, try to avoid the problem altogether, if you can.正如其他答案所建议的那样,如果可以的话,尽量避免这个问题。 For example, you can use instanceof to detect whether a given Person is a Male or Female , and only call getPregnancyMonth if the Person is a Female .例如,您可以使用instanceof来检测给定的PersonMale还是Female ,并且只有在PersonFemale时才调用getPregnancyMonth

Edit , in response to comment: the use of a factory method as described is largely pointless.编辑,回应评论:使用所描述的工厂方法在很大程度上是没有意义的。 If we ignore those people who don't wish to be labelled with a "normal" gender, you'll only ever create a Male or a Female object - you're much better just having public static Female createFemale ( ) and public static Male createMale ( ) methods in your Factory .如果我们忽略那些不希望被标记为“正常”性别的人,那么您将只会创建MaleFemale object - 拥有public static Female createFemale ( )public static Male createMale ( ) Factory中的public static Male createMale ( )方法。 This way, you'll avoid all this trouble you've been having.这样,您将避免所有这些麻烦。 It'll also get rid of the string being used like a enum (ie "male", or "female" as an argument to getPerson ), but that's a whole different matter...它还将摆脱像枚举一样使用的字符串(即“男性”或“女性”作为getPerson的参数),但这是完全不同的事情......

If you still want to use a combined factory method, you can cast the result as a Female :如果您仍想使用组合工厂方法,您可以将结果转换为Female

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

Or, if you have a Person that may or may not be a Female , you can cast that too:或者,如果您有一个Person可能是也可能不是Female ,您也可以使用它:

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

    female.getPregnancyMonth( );
}

I can't say I'm overly fond of either of those approaches though - they have their place, but there's usually a better way.我不能说我过分喜欢这两种方法中的任何一种——它们都有自己的位置,但通常有更好的方法。

It sounds like a broken object hierarchy, but taking it as stated, your interface needs two methods: isFemale() and getPregnancyMonth().这听起来像是一个损坏的 object 层次结构,但按照说明,您的界面需要两个方法:isFemale() 和 getPregnancyMonth()。 Then Male.getPregnancyMonth() throws an UnsupportedOperationException.然后 Male.getPregnancyMonth() 抛出 UnsupportedOperationException。 A better approach would probably be to design your model so that a Male could never be put into a position where his pregnancy month would be asked.更好的方法可能是设计您的 model 以便男性永远不会被放入 position 中,在那里会询问他的怀孕月份。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM