23

In java, what is a good way to design around a subclass that reduces the functionality of the superclass?

For example, consider the class "Man", that has the function "See" and the subclass "BlindMan" that shouldn't have that function, but should have everything else that "Man" has.

The only solution I can come up with is having an abstract class "Man", and two subclasses "SeeingMan" and "BlindMan", with SeeinMan adding a function "See".

However the problem with this solution is that if I now want to add a "DeafMan" class - what does it extend? SeeingMan? and what if that man is both deaf and blind?

indieman
  • 1,051
  • 2
  • 11
  • 24
  • 13
    You could of course have a `BlindDeafMan` as base class. Not very elegant in this example. Another (ugly) approach would be to throw UnsupportedOperationException in BlindMan.see (as certain iterators do for the remove operation). The last (and probably best) option would be to have an `Eyes` class referred to by a Man. You can then do `man.setEyes(new BlindEyes())`. – aioobe Jun 13 '13 at 06:30
  • 1
    Did you try to combine with interfaces ? – Rong Nguyen Jun 13 '13 at 06:33
  • You could create other subclasses of Man to be SingleHandicapMan and DoubleHandicapMan and if DeafMan and BlindMan both occur,extend them to DoubleHandicapMan if not extend them to SingleHandicapMan – alvinarul Jun 13 '13 at 06:34
  • 1
    See also the classic `Rectangle`-`Square` inheritance conundrum. – Richard JP Le Guen Jun 13 '13 at 06:36
  • 1
    Did I say `Rectangle`-`Square`? Apparently I meant [circle-ellipse problem](http://en.wikipedia.org/wiki/Circle-ellipse_problem). – Richard JP Le Guen Jun 13 '13 at 06:41
  • combine interfaces & the main abstract parent class – ehanoc Jun 13 '13 at 06:47
  • A blind man cannot be hired to do all the job that a man does. With the idea of interface based programming, it is a must that one object of one derived type could be swapped with another object of another derived type. Moreover, what is the meaning of 'inheritance' in this case? If the class B cannot get all what its base A has (ability to see) then it doesn't properly 'inherit' A. – PermanentGuest Jun 13 '13 at 09:24
  • It also depends on what you are going to do in the 'see' method. You could set up some attributes, like "rightEye" and "leftEye", with their values to 0 if blind, 10 if normal, 9.5 if myopic, and so forth. – Markon Jun 13 '13 at 13:55
  • An other solution can be to implement `See` as a no-op in `BlindMan` and add a `canSee` method in the base-class. Even though, doing this, you are basically doing by hand what the compiler could do for you. Instead of thinking of a `Man` as a single type, you should think of what are its abilities(hence go towards composition/interfaces). – Bakuriu Jun 13 '13 at 17:10

13 Answers13

14

I think you should use Composition rather than inheritance in this case, or have various subclasses that make up the human.

While I do understand your logic, a BaseClass is a contract, that guarantees all classes of that type should adhere to this behavior, having a subclass that removes the parent method is a big NO NO..

While you could throw various exceptions, I wouldn't go down that path at all. Think about it this way, say I am a developer who only needs to access Human object, I expect a certain behavior, and all of a sudden I call an interface method and get..an Exception just because I called it?? You should not be aware of the derived classes implementations and when you can or cano't call them.

Here are a few solutions:

Make Human a composition of BasicHumanFunctions, VisionSystem, etc. Then blind man would have only a few of those.

class Human {
  private BasicHumanFunctions _basicFunctions; //contains breathe funcitonality.
  private VisionSystem _vision; //contains see
}

class BlindMan {
   private BasicHumanFunctions _basicFunctions;
}

Make Human base class contain only the same behaviour all humans would like breathing etc, and then create a HealthyHuman and a BlindHuman etc, each creating their own methods. You can then use HealthHuman and subclass that further if you need.

class Human {
   void breathe() {};
   // other Human basic functions;
} 

class HealthyHuman extends Human {
   void see() {};
   //other healthy human functions
}

class BlindHuman extends Human {
  void useCane() {};
}

For the second case you can still use composition too to share behaviour:

class BlindHuman extends Human {
   private VoiceSubsystem _voice = new VoiceSybsystem();
   void speaker() {  _voice.speaker();}
}
Dory Zidon
  • 10,497
  • 2
  • 25
  • 39
  • 3
    I consider it only a NO NO when the Exception is a RuntimeException and thus unexpected. If the Interface declares the Exception, you will have to handle it anyway. (Because even a seeing person could be blinded in this very moment) – Angelo Fuchs Jun 13 '13 at 06:44
  • 1
    I much rather create an object without that method, over throwing an exception, which in a way states that he should be aware of which derived class implemented it...Blind man has no vision, it's not that he has vision that throws an exception :) IMO you do not want to change the base contract..if you need a different contract that means you prob need another way to handle it. Not saying that mine is the best, there are other options too..but I wouldn't never make a base method not work all of a sudden.. – Dory Zidon Jun 13 '13 at 06:46
  • 1
    So would you make a 3rd class BlindAndDeafHuman to combine the two? What if you then needed a collection of humans who are deaf? your List would not include those who are deaf and blind unless BlindAndDeafHuman extends DeafHuman, which brings us to square 1 – indieman Jun 13 '13 at 07:40
  • I like the composition, but the problem(from what is asked) is more behavioral than structural. Your composing the classes properties and features, but from a client's perspective (user of the classes) , you have to deal with concrete instances, missing the behavior for each persons TYPE (blind or healthy); I would suggest adding interfaces, clearly defining what each person-type is capable of performing(or not). – ehanoc Jun 13 '13 at 08:42
  • @bmartins I agree it's behavioural, however reaching is certain behavior is effected many times by the structure, I agree about Interfaces however, I think it is wise to do it that way. – Dory Zidon Jun 13 '13 at 10:53
  • 1
    @indieman I get what you're saying and I believe that adding interfaces would resolve that which is the way to do something like multiple inheritance in Java.. – Dory Zidon Jun 13 '13 at 10:54
8

The most important principle, is Lyskov's substitution principle.

Once you get it and apply it, you can build your model however you want.

For example, you could say that a blind man still sees, only he only gets black (or grey) pictures. There's also the question of legally blind people you want still see something if a blurred or partial picture.

You could also say that the action the object can do is not see. What we do is to watch. Seeing is the (successful) result of watching. Even with working eyes, you may watch without seeing anything! And blind people can still "see" something without eyes, or with non-functioning eyes, by listening (thus hearing, and building a mental "picture").

So, forget about "see" and "hear". Use watch and listen. And expect nothing from that. (wide pre-conditions).

informatimago
  • 147
  • 1
  • 4
4

Go for Interfaces.

Define interface for CommonMan which has common properties and use individual interfaces For seperate subClasses which have their specific methods.Then you can get the Both the interface methods.

Example:

public class SpecificMan extends CommonMan implements specifiManInter

{

//methods of CommonMan

//Methods of SpecificMan 

}

CommonMan Class:

public class CommonMan implements CommonManInter {

 //methods of CommonMan

}
Suresh Atta
  • 120,458
  • 37
  • 198
  • 307
4

Dory has it right about favoring composition over inheritance. Your question/problem is pretty much the same as the flying fish problem. In this example, how should we handle a creature that can fly and swim?

enter image description here

It would be awkward to fit FlyingFish into the inheritance hierarchy. Instead of trying to make that happen, use the power of composition:

enter image description here

Now, each of the concrete classes can specify their behavior. And this is the appropriate place to do so, based on the information expert principle: Information Expert will lead to placing the responsibility on the class with the most information required to fulfill it.

Note: It's difficult to read the benefits from the above screenshot, so here they are again:

Benefits
- Favor object composition over inheritance
- Forces developer to make a conscious decision about behavior when coding it (as opposed to creating default implementations in the base class that the developer must remember to override).
- By abstracting the varying behavior, it is now available for use by other clients.
- Being more loosely coupled means it’s easier to adhere to the open/closed principle, where code should be open for extension but closed for modification.

Bob Horn
  • 33,387
  • 34
  • 113
  • 219
  • 1
    a flying fish is most definitely NOT a bird. A person who can't hear is deaf, a person who can't see is blind, what do you do with a person who can't hear and can't see? do you define them as blind and give them a HearNoWay? If i were a programmer who encountered a structure like this, I would make the assumption that I can collect all the people who can't see in an ArrayList, but that's not true... you'd have to have ArrayList which will contain BlindMan and BlindDeafMan objects. – indieman Jun 14 '13 at 07:41
  • I'm guessing its just a caveat of OOP and classification in general – indieman Jun 14 '13 at 07:42
  • Using composition, like my example, what's to prevent you from having a list of men who are blind? – Bob Horn Jun 14 '13 at 13:53
1

In the class Man add hasEyes which is true by default, and in BlindMan make it false by default (or make blind men instantiations of Man that have their eyes robbed immediately after, e.g. a BlindManFactory). Then in Man's See code it so that if he does not have eyes it automatically fails.

Patashu
  • 21,443
  • 3
  • 45
  • 53
1

you could use boolean

e.g : isSeeing()

and in your function you could use that in your if else statement

Mostafa Jamareh
  • 1,389
  • 4
  • 22
  • 54
  • What a blind suggestion ^_^ – Suresh Atta Jun 13 '13 at 06:38
  • Think positive: isSeeing() is better than isBlind() -> that goes for everything that is some kind of negative: Use the positive form to avoid structures like if(!isNegative()) -> if(isPositive()) is easier to understand and maintain. – Angelo Fuchs Jun 13 '13 at 06:40
  • that's the whole issue though... You don't want SeeingMan to extend BlindMan (because a seeing man is not a blind man who can see) and you don't want Man to lack the functionality of seeing – indieman Jun 13 '13 at 07:30
1

In java, what is a good way to design around a subclass that reduces the functionality of the superclass?

That basically asks "how can inheritance to reduce functionality?". An example of this in Java I can think of is the Collections#unmodifyableList method, which says:

Returns an unmodifiable view of the specified list. This method allows modules to provide users with "read-only" access to internal lists. Query operations on the returned list "read through" to the specified list, and attempts to modify the returned list, whether direct or via its iterator, result in an UnsupportedOperationException.

So that's what I would go for when wanting to remove a certain feature. However, make sure that the usage of it is clear, e.g. state in the Javadoc of BlindMan that see() will result in an Exception.

However, If you want to "reduce" more than one feature, maybe independently, and changing them with the time, I would rather use variables than inheritance. In the end, you are not extending the superclass, so why abusing inheritance for this? What you have is a human with different properties.

The behaviour of the methods need to be documented. I could think of the following class for your usecase:

public class Human {
    private boolean seeing;

    public void setSeeing(boolean seeing) { ...}
    public boolean isSeeing() { ... }

    /**
     *  Returns what the human sees at the moment, or null
     *  if he/she can't see (seeing is false).
     */
    public String see() {
        if(seeing){
            return "I can see a tree!";
        }else{
            return null;
        }
    }

    // same goes for hearing
}
Uooo
  • 6,204
  • 8
  • 36
  • 63
1

Let the human do things his way, giv him tasks, not commands.

Seeing is part of some activity so let him use sight (or not) independely.

Eg tell him to travel somewhere. Healthy human will use sight, blind man will use other senses and will be less efficient (unless its in total darkness).

If vision is necessary for given task (eg. guard on guard tower) you need to ask how good is their sight (there are not blind people with unsifficently good sight).

Sometimes you want to ask them what they see (and not care what they hear etc.) Then just ask and expect blind (and other visually impaired) to not see anything.

If you want humans to be passive objects and some other object to process them, one not yet mentioned approach is: look at entity-componet programming used in game programming. It basically is using composition in generic way. Entities hold only identity, components holds data about some aspect of entity (eg. sight could be eg. number of dioptries or some more usefull stats) and Systems process sets of entities that have component combination required by given system. Sight system could require sight component and create component seenEntities containing what entities current entity see right now. Other system could merge results from all senses and use it to perform something usefull.

Alpedar
  • 1,314
  • 1
  • 8
  • 12
1

For example, consider the class "Man", that has the function "See" and the subclass "BlindMan" that shouldn't have that function

You don't get it fully right. Blind man has the function "see" which does nothing (because there's no link between sensors and appropriate brain part, or the sensors are not functioning (return empty list of pixels or image of 0 size).

A good analogy: a Writer has function flush(), but what makes that function for StringWriter?

/**
 * Flush the stream.
 */
public void flush() { 
}

Well, nothing. There's nothing to flush. OK but why the close() throws IOException?

public void close() throws IOException {
}

It's not perfect, but the code works for all types of writers, even those for which flush is not relevant.

But wait, even for the seeing man function see() may return null or empty list. For example, when it's too dark. Just check for null/empty values and the code will work fine with that design.

Danubian Sailor
  • 1
  • 38
  • 145
  • 223
0

You could throw an Exception in cases where you don't want the function to be called.

e.G. in your scenario: InablityException

like this:

public interface Man {

    public Object see() throws InabilityException;
    public Object hear() throws InabilityException;

}

public class BlindMan implements Man {
    public Object see() throws InabilityException {
       throw new InabilityException("blind people don't see");
    }

    public Object hear() {
       return "what I hear";
    }
}

And visa versa for the DeafMan.

Same thing works if Man is a class instead of an interface.

You could (and should) combine this with @Pataschu answer https://stackoverflow.com/a/17080626/881272 and throw the Exception if hasWorkingEyes() returns false.

Community
  • 1
  • 1
Angelo Fuchs
  • 9,825
  • 1
  • 35
  • 72
0

Interfaces :

I would define both behaviors (BlindMan and SeeingMan) through interfaces, exposing only the calls that define the type (BlindMan and SeeingMan). You shouldn't really care of what is the actual instance type underneath.

Abstract Parent Class :

Now, you can combine these interfaces with a "parent" abstract class that has all the default behavior(both blind and seeing ; if you choose too)

Combine the two :

public interface BlindMan {
         public void useBlindStick();
    }

   public interface SeeingMan {
        public void see();
   }


  public abstract class Man {
       public void useBlindStick() {
           //work
       }

       public void see() {
           //work
       }
  }


  public class SomeBlindMan extends Man implements BlindMan {
        //bla bla
  }


 public class SeeingMan extends Man implements SeeingMan {
       //bla bla
 }

Hope it helps

ehanoc
  • 2,187
  • 18
  • 23
0

How about something like this:

 public class Man {

    Ears ears;

    Eyes eyes;

    }

    public class Eyes {

    public boolean canSee()

    }

    public class Ears {

    public boolean canListen()
    }

then the logic would be like...

if(man.getEyes().canSee()){ //not blind

}
else
{
//blind logic
}

if(man.getEars().canListen())
{
//Not Deaf
}
Manish
  • 3,913
  • 2
  • 29
  • 45
0

To implement a capability, use interface.

To extend or redefine a functionality, use child class by extending base class.

If you want to add behaviour dynamically at run time, implement Decorator pattern.

Related SE posts:

Implements vs extends: When to use? What's the difference?

When to Use the Decorator Pattern?

Ravindra babu
  • 37,698
  • 11
  • 250
  • 211