Reputation: 11
I am wondering if it is possible to skip a class in the inheritance three if you want to inherit a method from the original base, not your direct predecessor.
For example, lets say I have three classes, GrandParent, Parent (inherits from GrandParent) and Child (inherits from Parent). GrandParent has a method Adresse, and Parent has a method Adresse who overrides this. However, say that for some reason, I want Child to have the same Adresse method as GrandParent, not Parent. Is that possible or have I messed up if I get in a situation like that?
The example code below is in C#
class GrandParent
{
private String Adresse;
public GrandParent()
{
}
public virtual void setAdress(String Adresse)
{
this.Adresse = Adresse;
}
public String getAdress()
{
return Adresse;
}
}
class Parent : GrandParent
{
public Parent()
:base()
{
}
public override void setAdress(String Adresse)
{
base.setAdress("Home: " + Adresse);
}
}
class Child : Parent
{
public Child()
: base()
{
}
}
Upvotes: 0
Views: 182
Reputation: 5132
There isn't a clean way to "skip a class in the inheritance tree". If you find yourself needing to do this (because there's only one method out of many with this bastardized requirement), I'd suggest removing the inheritance entirely, using a readonly delegate in the top-level class to define the default behavior, and allowing each subclass to either create its own delegate or (if it wants the top-level behavior instead of its parent's) reset to the top-level delegate:
delegate string GetMyAddress(string baseAddress);
class Grandparent
{
protected readonly GetMyAddress _baseGetMyAddress;
protected GetMyAddress _getMyAddress;
public string BaseAddress = "Foo Street";
public Grandparent()
{
_baseGetMyAddress = (a) => { return String.Format("Grandparent: {0}", a); };
_getMyAddress = _baseGetMyAddress;
}
// no longer virtual
public string MyAddress()
{
return _getMyAddress(BaseAddress);
}
}
class Parent : Grandparent
{
public Parent()
{
// does something differing from the base
_getMyAddress = (a) => { return String.Format("Parent: {0}", a); };
}
}
class Child : Parent
{
public Child()
{
// does what its parent tells it to do
}
}
class ChildTakingAfterGrandparent : Parent
{
public ChildTakingAfterGrandparent()
{
// does what its grandparent does
_getMyAddress = _baseGetMyAddress;
}
}
class WillfulChild : Parent
{
public WillfulChild()
{
// does its own thing
_getMyAddress = (w) => { return String.Format("WillfulChild: {0}", w); };
}
}
public static void Run()
{
var gp = new Grandparent();
var p = new Parent();
var c = new Child();
var cg = new ChildTakingAfterGrandparent();
var wc = new WillfulChild();
Console.WriteLine("gp.MyAddress(): \"{0}\"", gp.MyAddress());
Console.WriteLine("p.MyAddress(): \"{0}\"", p.MyAddress());
Console.WriteLine("c.MyAddress(): \"{0}\"", c.MyAddress());
Console.WriteLine("cg.MyAddress(): \"{0}\"", cg.MyAddress());
}
Invoking the Run()
method will display the following:
gp.MyAddress(): "Grandparent: Foo Street"
p.MyAddress(): "Parent: Foo Street"
c.MyAddress(): "Parent: Foo Street"
cg.MyAddress(): "Grandparent: Foo Street"
wc.MyAddress(): "WillfulChild: Foo Street"
Upvotes: 0
Reputation: 2623
If you have that kind of problem, it means that your application is poorly designed. You need to learn about SOLID design principles. In this case, Liskov substitution principle would be useful. When using inheritance, always verify that the relationship is an IS-A.
Code reuse should ideally be done by composition instead of inheritance.
If you still want to use inheritance, I can think a few approach to this problem.
First possibility would be to add NewChild
class that would be used instead of Parent
and functionality that is specific would be in that class and shared functionality would be kept in the existing Parent
. You might decide to keep existing name for the new child however and find another name for the existing class.
Another less clean possibility, is to add some protected methods for code sharing purpose.
But I think it might be better if you want to keep original hierarchy as it to modify Parent.setAddress
method so that the special behavior is dependant on something else like a boolean passed to the constructor.
Essentially, inheritance should follows IS-A rules and other means should be used for code reuse. It might be some protected methods for potentially common parts or even other classes.
Upvotes: 3