-2

So, I've been asked to turn 2 classes that inherit the same interface into one.

SimpleData class would be provided with implementations of IHelper and IDataHelper interfaces in the constructor.

Let's take IDataHelper.

There is a function definition that reads bool HasWarnedUser().

I had 2 separate classes of SimpleData. One in a .NET Standard project library, and one in a .NET Framework library.

SimpleData in the .NET Standard library implements the HasWarnedUser function inheriting from IDataHelper with a throw new Unimplemented() exception, i.e.

    public bool HasWarnedUser()
    {
      throw new NotImplementedException("Please provide implementation for this function call");
    }

The SimpleData in the .NET Framework library implements it like so:

    public bool HasWarnedUser()
    {
      MessageBox.Show("SomeMessage", "SomeCaption");
      return true;
    }

This is just a basic example (ignore the code per say - it's not doing anything smart or anything that would make proper sense).

I've been told to just have one SimpleData class that would be provided with implementations of IHelper in the constructor.

What does this mean?

When declaring a new SimpleData object, how would we determine what is placed into the constructor?

If anyone understands, I'd appreciate an explanation :).

Thanks!

  • 3
    That looks more specifically like [dependency injection](https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection). By using dependency injection, consumers of the `SimpleData` type can inject their own user interaction methods without having to subclass anything, or make `SimpleData` depend on any UI framework. See [Difference between dependency and composition?](https://stackoverflow.com/q/21022012) and [Is dependency injection by hand a better alternative to composition and polymorphism?](https://softwareengineering.stackexchange.com/q/151215). – dbc Jul 21 '23 at 01:09

1 Answers1

1

In the context of "Composition Over Inheritance" in C#, it means favoring composition (building complex objects by combining simpler ones) rather than relying solely on inheritance (creating a hierarchy of classes). Instead of inheriting behavior from parent classes, you create classes that contain instances of other classes (composition) to achieve the desired functionality.

In the given scenario, you have two classes in different libraries that both implement the same interface, IDataHelper. The goal is to merge these classes into a single SimpleData class by using composition instead of inheritance.

To accomplish this, you would create a new SimpleData class that accepts an implementation of the IHelper interface in its constructor. The constructor parameter would allow you to inject the specific implementation of IHelper when creating a new instance of SimpleData.

For example:

public interface IHelper
{
    // Define helper methods here
}

public interface IDataHelper
{
    bool HasWarnedUser();
}

public class SimpleData : IDataHelper
{
    private readonly IHelper _helper;

    public SimpleData(IHelper helper)
    {
        _helper = helper;
    }

    public bool HasWarnedUser()
    {
        // Use the injected helper implementation to determine if the user has been warned
        return _helper.CheckWarningStatus();
    }
}

Now, when creating a new instance of SimpleData, you would need to provide an implementation of IHelper in the constructor. This allows you to customize the behavior of SimpleData based on the specific implementation of IHelper you provide.

For example:

IHelper helperImplementation = new SomeHelperImplementation();
SimpleData simpleData = new SimpleData(helperImplementation);

By using composition and injecting the necessary dependencies, you can achieve flexibility and modularity in your code. This approach allows you to separate concerns and easily switch out different implementations of IHelper without modifying the SimpleData class itself.