• Post Reply Bookmark Topic Watch Topic
  • New Topic

Altering Parent Method's Behavior by Overriding Method It Calls  RSS feed

 
Stevens Miller
Bartender
Posts: 1445
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have two classes (Daughter and Son) that contain some very similar method definitions:



Each of those classes has a "speak" method with two out of three lines being identical. I could move those into a parent class, but I need each of the child classes to continue to exhibit its unique behavior. I'm trying the approach below, which replaces the unique code with a call to a "placeholder" method that must be implemented by each child class:



This works and moves the shared code from two places (the Daughter and Son classes) into one place (the new Mother class, which is now a parent class of Daughter and Son). Something about this feels a bit odd to me, though. It's one thing for a child class to override a parent class's methods to extend or alter their behavior. But, here, I've implemented an abstract method in the parent class to alter what happens when the parent class's method (speak(), in this case) is called, without overriding that parent class method itself.

Forgive me for not being more specific in how I ask this, but is that a good technique?
 
fred rosenberger
lowercase baba
Bartender
Posts: 12565
49
Chrome Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
well...most people here would say that this design in general isn't good. When class 'B' extends class 'A', you should be able to say "B is an A". that doesn't work here: "a Son is a mother" or even "a Son is a Family". quite often, "a Daughter is a mother" doesn't even work.

So that my be a poor choice of naming. Instead of "Family", you could have a class name "FamilyMember", and then all the relationships work..."a Son is a FamilyMember", "a Daughter is a FamilyMember".



now..that is not your question.

In general, it IS a good idea to remove duplicate code to a parent class. I may change the sayKindOfOffspring() method to ONLY return the relationship type, and not the ", ". the method should do exactly what it says it does, and no more. You can control the formatting in the Mother.speak() method. You may at some point want to print a sentence like:

"I gave my Son his allowance"

and for that, you don't want the comma. If the Son/Daughter class always returns a comma, you are stuck with it.
 
Stevens Miller
Bartender
Posts: 1445
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
fred rosenberger wrote:well...most people here would say that this design in general isn't good. When class 'B' extends class 'A', you should be able to say "B is an A". that doesn't work here: "a Son is a mother" or even "a Son is a Family". quite often, "a Daughter is a mother" doesn't even work.

So that my be a poor choice of naming. Instead of "Family", you could have a class name "FamilyMember", and then all the relationships work..."a Son is a FamilyMember", "a Daughter is a FamilyMember".

Liskov substitution principle, right? Yes, agreed.

now..that is not your question.

No, and thanks for speaking to that. The class names were to emphasize the relationships; your suggested alternatives would make far better sense in a real application.

In general, it IS a good idea to remove duplicate code to a parent class. I may change the sayKindOfOffspring() method to ONLY return the relationship type, and not the ", ". the method should do exactly what it says it does, and no more.

Heh, yeah. I saw that after posting my question. That's the kind of the thing that creeps in when I try to pare down the example to something that illustrates the question. The original code giving rise to this post actually has nothing at all do with sons, daughters, moms, or pops.

You can control the formatting in the Mother.speak() method. You may at some point want to print a sentence like:

"I gave my Son his allowance"

and for that, you don't want the comma. If the Son/Daughter class always returns a comma, you are stuck with it.


Thanks. So, would you say I'm on a good track with the basic methodology of moving shared code into a superclass (my attempt to follow the Don't Repeat Yourself rule), while using an override in the subclass to allow the shared superclass code to exhibit different behaviors across subclasses? (The fact that I can't even ask the question without using such wordy, clunky phrasing has me a bit nervous about this. On the one hand, the approach I'm using kind of reminds me of some design patterns I've read about recently. But, on the other hand, most good, clean OOP designs seem to have similarly good, clean plain-language descriptions to go with them.)
 
Stevens Miller
Bartender
Posts: 1445
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Oh, hey! Your suggested changes actually do a lot to help me put more faith in this approach, Fred. Here's the code again, with your changes added:



When I think of the superclass with its new name, "FamilyMember," it's much easier to accept the idea that the sayKindOfOffspring() method is overridden in a subclass, as the subclass isn't altering the parent class behavior so much as it is completing its definition. Instances of both subclasses (Daughter and Son) are, indeed, FamilyMember objects. But leaving the sayKindOfOffspring() abstract in the FamilyMember class definition makes it clear that only a more specific subclass of FamilyMember can say what it is. That's quite enlightening, since the compiler couldn't care less what I call each of these classes, but a simple change of name to reflect their relationships makes this design decision a lot easier to embrace.

Thanks, bro'!
 
Mike. J. Thompson
Bartender
Posts: 689
17
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
What you have described there is the Template Method design pattern. You have a super class that provides an implementation of an algorithm, but it also has one or more (usually protected) abstract methods that allow sub classes to provide parts of the implementation.

It's similar to the Strategy pattern in that you have an algorithm that calls out to external hooks to allow the behaviour to be customised to different situations. The difference is that the Strategy pattern allows the caller to alter the behaviour by passing in a Strategy object (often a functional interface), but the Template Method pattern allows the specific implementation of the abstract class to alter the behaviour.
 
Stevens Miller
Bartender
Posts: 1445
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Mike. J. Thompson wrote:What you have described there is the Template Method design pattern.


Thanks, Mike! I had gone back and looked at my notes on design patterns, but couldn't make the connection (which probably means my notes need improvement). I dug out my copy of "Head First Design Patterns," looked up the Template Method Pattern, and saw at once that you are correct. That's very reassuring.

Many thanks to you and Fred for helping me out here.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!