• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Boat extends Car?

 
Ranch Hand
Posts: 71
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I would like to know the opinion of all the ranchers on one scenario. This scenario is something very similar to the one which we face right now.

Let�s say I have a class called �Car�. I don�t have any control on this class (I won�t be able introduce a new parent class to this class by moving some behaviors up).

Now I am going to write a new class called �Boat�. Now I find that my new class is a specialization of the class �Car� even though in a real world scenario it�s not. But it will be a perfect follower of Liskov substitution principle in an OO world.

Now my question is should the Boat extend Car?

If not how will you reuse behavior of Car?

If �Yes�, what are the points that helped you to come to this decision?
 
Ranch Hand
Posts: 48
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Why not reuse thru composition - maybe a decorator over Car?
 
Sheriff
Posts: 7001
6
Eclipse IDE Python C++ Debian Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I'd first extract out the things in Car that I want to reuse for boat into a base class (let's call it "Vehicle", for example), which is extended by Car. Then Boat can also extend Vehicle.

Does that make sense?
 
Bartender
Posts: 2968
6
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Manoj Kumkumath:
I don�t have any control on this class (I won�t be able introduce a new parent class to this class by moving some behaviors up).



Just a variation on the approaches already mentioned which lets you regain some control:
  • Define your own interface MyVehicle that exposes the minimum necessary methods currently used by clients on Car.
  • Create a new class MyCar that implements MyVehicle by containing and delegating to a private instance of Car.
  • Create a new class MyBoat that implements MyVehicle - with or without Car - it doesn't matter.
  • Replace the references to Car in your application with references to MyVehicle.



  • Refactoring: Extract Interface
    Refactoring: Replace Inheritance with Delegation
    [ May 25, 2007: Message edited by: Peer Reynders ]
     
    author
    Posts: 14112
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    I would be quite suspicious of such an inheritance relationship, but I wouldn't totally rule it out. "Real world" relationships are just a very rough heuristic for relationships in code, in my not so humble opinion.

    It's hard to discuss this on such an abstract example, thoug. Can you give us more information about the actual problem?
     
    Manoj Kumkumath
    Ranch Hand
    Posts: 71
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Peer,
    But all my existing Car(the reference) should run(method ) even if it is a
    Boat(of type).
     
    Manoj Kumkumath
    Ranch Hand
    Posts: 71
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    I wouldn't be able to explain the exact scenario.
    My apologies.....

    But let me try to explain as much as I can.

    We have a framework and we have applications which make use of that framework. Frameworks do provide some generic functionality to the applications which is common across the company business. As an example let's say sort is one such functionality. What framework does is helping the application to extract the data from say an excel and put it say an Sort object and pass it to application. The application takes care of the actual sorting.
    Now we have some other functionality say grouping data. So we need to group data and then apply some function on the group (for an example group all the users based on the country and find the average of their ages in each country).
    As functionality these two are different, but the way this framework handles is very similar. For an example for Sort, the framework should return the application a column row, rows of data and the names of columns on which sorting has to happen.

    In the case of grouping, it's going to be a column row, rows of data and the names of columns on which it has to be grouped and the name of the function like average.

    Also the way the framework grab this data is also the same with say some extra task for grouping.

    So if we can treat grouping as a type of sorting, most of the code is already available.
    [ May 25, 2007: Message edited by: Manoj Kumkumath ]
     
    Peer Reynders
    Bartender
    Posts: 2968
    6
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Originally posted by Manoj Kumkumath:
    But all my existing Car(the reference) should run(method ) even if it is a Boat(of type).



    Yes - which is fine as long as you are only dealing with direct instances of Car. However:
  • You have no control over Car.
  • and you are planning to create custom class by inheriting from a class that you have no control over.


  • This usually is the seed of big trouble.

    Furthermore existing code was able to assume that it was dealing with a direct instance of Car. By directly inheriting from Car you are subtly changing the semantics - which could render portions of the existing code incorrect. Code assuming that it is dealing with a direct instance of Car may actually be handed an indirect instance (i.e. a Boat). Some of your existing code may apply to vehicles, however the remaining code only applies to cars. Until now cars were the only entities in the system it wasn't necessary to disambiguate between the two. However now you need to differentiate the code that applies to MyVehicles, to MyCars, and to MyBoat.
    (Granted car code should go into Car and boat code should go into Boat, however a Marina should only accept Boats not Vehicles and the Indianapolis racetrack should accept Cars, not Vehicles.)
    [ May 25, 2007: Message edited by: Peer Reynders ]
     
    Peer Reynders
    Bartender
    Posts: 2968
    6
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Originally posted by Manoj Kumkumath:
    For an example for Sort, the framework should return the application a column row, rows of data and the names of columns on which sorting has to happen. In the case of grouping, it's going to be a column row, rows of data and the names of columns on which it has to be grouped and the name of the function like average.



    Basically you have identified a data access interface that needs to be extracted. There may even the command aspect to it.
    If you simply extend this object, things could get pretty confusing. "Why am I am a sorting here - oh, wait a minute this could be for grouping." There could easily be other "data manipulation processes" that would benefit from this interface. What about combining them? You want to sort and group - another class? You are better off defining a data access and command interface. Then create a holder class that implements the data access inteface and can trigger the operations - the operation objects can be injected into the holder and pipelined (sort first, then group).
     
    Ranch Hand
    Posts: 687
    Hibernate jQuery Spring
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Originally posted by Manoj Kumkumath:


    Let�s say I have a class called �Car�. I don�t have any control on this class (I won�t be able introduce a new parent class to this class by moving some behaviors up).

    Now I am going to write a new class called �Boat�. Now I find that my new class is a specialization of the class �Car� even though in a real world scenario it�s not. But it will be a perfect follower of Liskov substitution principle in an OO world.

    Now my question is should the Boat extend Car?



    No, It is better for the boat not to extend car as you yourself said "I don�t have any control on this class"

    What happens if some of the behaviour changes in car some time down the line..?


    Originally posted by Manoj Kumkumath:


    If not how will you reuse behavior of Car?



    Put a abstraction between car and boat declaring behaviour which you wanted to inherit from boat in car. In the abstraction layer contain boat and call the behaviour as requested by car. If in future boat changes, car need not change, the abstraction layer can then be changed to provide the service as was being previously provided by boat.



    Boat{

    paddle(){
    }

    skim(){
    }

    refuel(){
    Delegate.refuel()
    }
    }

    Delegate{
    Car car = new Car();

    refuel(){
    car.refuel()
    }

    }
     
    Manoj Kumkumath
    Ranch Hand
    Posts: 71
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    First thanks for all your replies


    Basically you have identified a data access interface that needs to be extracted. There may even the command aspect to it.


    I agree. Also we are trying to get some control over the Sort so that it can refactored out and to rename it to a more appropriate name (Since Sort is not actually a sort but more a data provider for sort). But this change is going to be massive.

    Now how will you approach this problem? Will you refactor the Sort framework first to come up with a generic contract in all the places or will you extend the Sort framework to handle Grouping also and show it working and then touch the Sort framework to make it more generic?
     
    With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
    reply
      Bookmark Topic Watch Topic
    • New Topic