Yahya Hussein
Yahya Hussein

Reputation: 9121

C# Modelling with Inheritance

I am struggling with modeling a problem I have, for simplicity I have converted it to Birds example:

Let us say that we have birds, some can fly, some can't, however, all of them have wings, and all the flying birds fly exactly the same way.

My question is what is more suitable for the flying ability? usually, abilities are represented using interfaces, but that would require me to implement the Fly method inside each Bird although they fly the same way.

Another question would be, a bird needs wings to fly, what could represent a "Need-A" relationship? it would be a "Has-A" relationship from the Bird class perspective, but from the module representing the flying ability, it would be a "Need-A" relationship.

Here is my current class diagram.

Class Diagram

To solve some of the above issues, I have converted the Bird to the abstract class which is inherited by CanFlyBird. Is this the correct way to go?

Because seems like I still need to figure out how to pass the Wings of Bird Class to Fly method by default.

Updated Class Diagram

Upvotes: 1

Views: 595

Answers (2)

Pranay Rana
Pranay Rana

Reputation: 176936

I have suggestion , you can take out CanFlyBird output of inheritance chain, and instead of that pass it via constructor , means make use of composition ,

so it will become

Bird get inherited to Eagle and Penguin , and you pass CanFlyBird as constructor argument to Eagle.

Code will be

interface IFly {
  void fly();
}

and CanFlyBird will be

   public class CanFlyBird : IFly {
     public void Fly() {}
   }

and Eagle will be

  public class Eagle : Bird {
     private readonly IFly _fly;
     public Eagle (IFly fly) {
        _fly = fly; 
     }
 }

My suggestion is make use of Composition instead of going to loan chain of inheritance.

By this way if I want to make variation of canFlyBird class I can create it without changing my existing class

So it will become Bird has a flying capability


or if you want to follow current structure then

you can make fly method as virtual method in CanFlyBird class, so if someone wants to override it, that class can override else use base version

Upvotes: 1

CDove
CDove

Reputation: 1950

You're on the right track, but I think your second question is basically, "how do I make sure I can't construct a wingless bird".

The "Need-A" relationship is still a "Has-A" relationship. You have two ways to implement the requirement.

First, you can make a default value for your property in your Bird:

Wing wings = new Wing(); //as a field or
public Wing Wings { get; set; } = new Wing() //as a property

or second, and probably more correctly in this situation, require a Wing in your constructor:

public Bird(Wing wing) { this.wings = wing; }

As for "Fly()" I concur with others and recommend a virtual method. You can override this later in your subclasses, and if you decided one day to count swimming as flying, allow you to make minimal changes to the Penguin subclass to implement your change.

Upvotes: 1

Related Questions