简体   繁体   中英

Understanding composition in C#

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:

  1. 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.

  2. 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, ie 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.

I think the SuperBot is a aggregration type object composition , but I am not 100% about the terminology that far into theory territory.

What you describe sounds like you want to do Multiple Inheritance. Unfortunately that one leads to the Diamond Problem . Wich was one of the many problems the .NET Developers wanted to avoid. So they declared: "Single Inheitance only". (Note that C# fully supports Multiple Inheritance, but here the Framework rules are more important).

.NET does have something somewhat similar to Multiple Inheritance: Interfaces . In lack of a better term, a Interface is "more abstract then a abstract class". Interface are not inherited, they are implemented. And as they do not carry any code, you can implement as many interfaces as you like without risking the dreaded diamond of death.

In your case, you propably want the Intefaces ICanBark, ICanMove and ICanClean. The concrete Dog, Robot and Cleaner classes implement one of them. The SuperBot all 3.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM