开发者

Interface with two different implementations

I have an interface Person and I have 2 classes Female and Male that implement the interface.

For the Female class, I have a method getPregnancyMonth that my Male class does not have. Adding that method to my interface Person becomes a problem as my Male class now needs to inherit that method from the interface; but the male would never be pregnant.

What would be a solution, do I need to extend Person instead of 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.

    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开发者_JS百科 is, since my interface has getPregnancyMonth, my male has to add that method to the concrete class to implement the interface. Is there a way to avoid this?


getPregnancyMonth Should not be in the interface of 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.

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. 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.

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:

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:

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.


In my opinion, getPregnancyMonth is not generic enough to be in a Person interface. It should probably be defined in the Female class only.

You may also define a second interface containing that getPregnancyMonth. Female will implement both.


Don't add getPregnancyMonth to 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. 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.

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. 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 (i.e. "male", or "female" as an argument to getPerson), but that's a whole different matter...

If you still want to use a combined factory method, you can cast the result as a 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:

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.


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. 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.

BTW By this I don't mean throw in an if(person instanceof Female), design your heiarchy as to avoid this.


It sounds like a broken object hierarchy, but taking it as stated, your interface needs two methods: isFemale() and getPregnancyMonth(). Then Male.getPregnancyMonth() throws an 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜