1

I have some abstract base classes to be used on multiple implementations.

Base classes:

public abstract class BaseX
{
    public string A { get; set; }
}

public abstract class BaseY : BaseX
{
    public string B { get; set; }
}

For each use case, I want to create from these base classes specific classes like:

public abstract SpecificX : BaseX
{
    public string C { get; set; }
}

public abstract SpecificY : BaseY
{
    public string D { get; set; }
}

All classes that derive from SpecificY should contain all the properties A, B, C, D.

My problem now is, that SpecificY doesn't have the property C from SpecificX, because I cannot do multiple inheritance like

public abstract SpecificY : BaseY, SpecificX

My only idea would be to use Interface like this:

public Interface ISpecificX
{
    string C { get; set; }
}

public abstract SpecificX : BaseX, ISpecificX
{
    public string C { get; set; }
}

public abstract SpecificY : BaseY, ISpecificY
{
    public string D { get; set; }
    public string C { get; set; } <== redundancy
}

But then I'd need to implement C twice. And as soon as C is becoming more than a simple Property, things get ugly. Is there a better way to create this structure?

Thanks in advance,
Frank

Aaginor
  • 4,516
  • 11
  • 51
  • 75
  • insteaf of **inheriting** you may consider to **use** instances of what you think your base-class should be. This way you can have one, or two or even none at all of those properties. – MakePeaceGreatAgain Nov 11 '20 at 10:19
  • 1
    Does this answer your question? [Multiple Inheritance in C#](https://stackoverflow.com/questions/178333/multiple-inheritance-in-c-sharp) and look for [Chris's answer](https://stackoverflow.com/a/178368/585968) on _composition_. –  Nov 11 '20 at 10:30
  • 2
    please correct your question as I can't see any class like `SpecificB` or `SpecificA` from it – Formula12 Nov 11 '20 at 10:52
  • Sorry, misstyping with SpecificB|A ... corrected it in the question – Aaginor Nov 11 '20 at 10:56
  • @MickyD Thanks for the link. It's not really answering the question, or let's say, I am very unhappy with a composition solution and would probably rather do a Interface workaround to reduce the overhead to redundancy in SpecificY and what lies beyond – Aaginor Nov 11 '20 at 11:26
  • @Aaginor _"[composition]...Thanks for the link. It's not really answering the question"_ - considering you stated _"My problem now is... `I cannot do multiple inheritance`"_ and a C# _["class can have only **one direct base class**"](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/inheritance)_ the popularity of the link would seem to suggest otherwise. You also mentioned _"redundancy"_, that's something composition/aggregation can help to alleviate. –  Nov 12 '20 at 09:02
  • What's not working: Attributes, Inheritance (So a function that takes a SpecificX cannot take a SpecificY), Redundancy (why do you have this in "exclamation marks"?) – Aaginor Nov 12 '20 at 11:12

1 Answers1

1

I would strongly suggest to favour composition over inhertiance - as propsed by the GoF. This way you do not inherit a given class, but just use an instance of it. Then you can easily have all your properties without any duplication:

class BaseX { ... }
class BaseY { ... }

class SpecificY : BaseY
{
    private readonly SpecificX b = new SpecificX();
    public string A { get => this.b.A; set => this.b.A = value; } // delegate the call
    public string B { get; set; }
    public string C { get => this.b.C; set => this.b.C = value; } // delegate the call
    public string D { get; set; }
}
MakePeaceGreatAgain
  • 35,491
  • 6
  • 60
  • 111
  • The problem with composition-over-inheritance is that you can't pass a composed (member) object around as though it were a reference to its owner - nor can you override methods either. Composition-over-inheritance works best in languages based on message-passing (like Smalltalk and Objective-C) or languages with first-class support for mixins and traits (thus allowing for polymorphism). C# has neither message-passing or traits - which makes polymorphic class-composition a very painful and frustrating experience. – Dai Nov 11 '20 at 10:53
  • Yes, f.e. if I want to pass a variable of type SpecificX, I can't pass an object of SpecificY. Also, I very often use the construct: if (myObject is SpecificX specificXInstance) { ... } which would not work with composition. This could be solved with Interfaces, but then I am back at start, because I need to make sure that all new properties/methods from SpecificX are in SpecificY as well. – Aaginor Nov 11 '20 at 11:22
  • Also, I use attributes for the properties, which would probably not appear on the delegated properties. – Aaginor Nov 11 '20 at 11:50
  • @Aaginor _"if I want to pass a variable of type SpecificX, I can't pass an object of SpecificY"_ - that is a limitation of your code and is present whether composition is used or not. The only commonality in your two graphs is that that `SpecificX` and `SpecificY` ultimately derive from `BaseX` so there is nothing stopping you from passing an instance of `SpecificY` in this case. Also performing explicit checks like `if (myObject is SpecificX specificXInstance) ` defeats the purpose of OOP. I think you need to rethink your trees –  Nov 12 '20 at 08:42
  • @MickyD Well, this is exactly what I am asking for. – Aaginor Nov 12 '20 at 11:06
  • 1
    @Aaginor what I am saying is that your inheritence trees don't appear to make sense. e.g. if you were to replace `BaseX`, `BaseY`, `SpecificX` and `SpecificY` with say `Animal`, `Dog`, `Cat` and `Husky` you will soon see why `public abstract SpecificY : BaseY, SpecificX` doesn't work. There is no creature on Earth that had a cat as one parent and a dog for another...a husky one at that! ;) Your example of _"I want to pass a variable of type SpecificX, I can't pass an object of SpecificY"_ _can_ hold true if the method was fine to work on `Animal`. Hope this helps –  Nov 12 '20 at 11:35