I wanted to gain a better understanding of composition over inheritance. I watched a few tutorials which explain the concepts very well but using languages I am more familiar with such as Python. However, I am learning C# at the moment and am struggling to implement what I have learned on the subject and wondered if anyone could help. Here is the code I have:
using System;
namespace Composition
{
class Program
{
static void Main(string[] args)
{
SuperBot steven = new SuperBot(new Dog(),new Robot());
steven.Bark();
}
}
class Dog
{
public void Bark()
{
Console.WriteLine("Woof");
}
}
class Robot
{
public void Move()
{
Console.WriteLine("I'm moving!");
}
}
class CleanRobot
{
public void Clean()
{
Console.WriteLine("Just keep dusting, just keep dusting");
}
}
class SuperBot
{
// can clean, move and bark
public Dog o1;
public Robot o2;
public CleanRobot o3;
public SuperBot(Dog dog, Robot robot)
{
this.o1 = dog;
this.o2 = robot;
}
}
}
Essentially, I have a Dog
that can bark
, a Robot
that can move
and a CleanRobot
that can clean
. I want to create a SuperBot that can move, bark and clean, and use composition to achieve this.
I have two main questions:
The above is what I have coded so far, but yet it will not allow me to call the Bark
method on my SuperBot
object, as it says SuperBot
class doesn't contain this method.
How would I use composition in the case where my Dog
class could also Eat()
but I do not want to use this method for my SuperBot
class?
Really appreciate any help - struggling to get my head around this!
UPDATE - ATTEMPT USING INTERFACES
using System;
namespace Composition
{
public interface ICanBark
{
string Bark();
}
public interface ICanMove
{
string Move();
}
public interface ICanClean
{
string Clean();
}
class Program
{
static void Main(string[] args)
{
SuperBot steven = new SuperBot();
steven.Bark();
}
}
class Dog : ICanBark
{
public string Bark()
{
return "Woof";
}
}
class Robot : ICanMove
{
public string Move()
{
return "I'm moving";
}
}
class CleanRobot : ICanClean
{
public string Clean()
{
return "Just keep dusting, just keep dusting";
}
}
class SuperBot : ICanBark, ICanMove, ICanClean
{
public string Bark()
{
return "Barking";
}
}
}
When using composition as in your example, you unfortunately have to implement the exposed methods in the composing class as well:
class SuperBot
{
// can clean, move and bark
public Dog o1;
public Robot o2;
public CleanRobot o3;
public SuperBot(Dog dog, Robot robot, CleanRobot cleanRobot)
{
this.o1 = dog;
this.o2 = robot;
this.o3 = cleanRobot;
}
public void Bark() => o1.Bark();
public void Move() => o2.Move();
public void Clean() => o3.Clean();
}
This will solve your compiler error. Also if you add more methods to Dog
, Robot
or CleanRobot
, they will not impact what the SuperBot
offers, i.e. if Dog
has a method Eat()
, SuperBot
will not have this method unless you add it as well.
Conceptually you use composition like this, if you model a SuperBot
as actually consisting of a Dog
, a Robot
and a CleanRobot
. The SuperBot
then uses its Dog
to bark and its CleanRobot
to clean.
Edit (from comments):
If you want to have a function that calls Bark
public void GoodBoy(Dog dog)
{
dog.Bark();
}
You cannot pass a SuperRobot
to this method. In that case you need a common interface for Dog
and SuperRobot
that contains the Bark
method.