I don't know how to use a dependency injection in an abstract class. Let me show you my problem in a simple example:
public abstract class Animal {
public abstract void Move();
public void Sleep()
{
restService.StartSleeping(1000); //how to get this service here?
}
}
public class Cat : Animal
{
public readonly IMotionService _motionService;
public Cat(IMotionService motionService)
{
_motionService = motionService;
}
public override void Move()
{
_motionService.Run();
}
}
public class Bird : Animal
{
public readonly IMotionService _motionService;
public Bird(IMotionService motionService)
{
_motionService = motionService;
}
public override void Move()
{
_motionService.Fly();
}
}
Every animal move in different way so the Move() function is implemented separately in every derived class. As you probably noticed the whole implementation comes from the motionService.
On the other hand all animals sleep in same way, so I want put the Sleep() implementation in a base abstract class to avoid a duplication code, but I can't use my restService with a Sleep implementation because I don't have idea how to inject a service class into an abstract class.
I thought about IServiceProvider but it should be injected too.
You pass it down like this:
public abstract class Animal
{
private readonly IRestService restService;
public Animal( IRestService restService )
{
this.restService = restService;
}
public abstract void Move();
public void Sleep()
{
restService.StartSleeping(1000);
}
}
public class Cat : Animal
{
// vv Should be private!
public readonly IMotionService _motionService;
public Cat(IMotionService motionService,
IRestService restService)
: base(restService) // pass on to base class ctor
{
_motionService = motionService;
}
public override void Move()
{
_motionService.Run();
}
}
// Same in `Bird` class
For reference: Using Constructors (C# Programming Guide)
Related
I've been trying to apply SOLID principles more consciously on my current project. Using interfaces to create the abstraction and allowing classes that are handling the dependency injection to provide the concretions has really helped with decoupling some of the code and (hopefully!) making it more maintainable in the long run.
However, here and there I'm hitting a bit of a wall where it seems neither interfaces nor abstract classes work for the reason that there are functions for which I want an implementation defined.
This means:
Interfaces will not work since I can't define an implementation and obviously don't want to repeat the code in all implementing classes
Abstract classes will not work because I cannot derive from multiple classes
Some super simple code to illustrate the problem:
public abstract class Vehicle
{
public void MoveForward()
{
// Some code here
// This implementation is always the same
}
public abstract void PerformUniqueAbility(); // This is for the derived class to implement
}
public abstract class RadioSignalBroadcaster
{
public void StartBroadcast()
{
// Some code here
// This implementation is always the same
}
public abstract void PerformUniqueBroadcastingAbility(); // This is for the derived class to implement
}
Now of course what I'd like to do is this:
public class MyNewClass: Vehicle, RadioSignalBroadcaster
{
// Class that contains the implementations for both MoveForward() AND StartBroadcast() but also allows me to define
// bodys for the abstract methods
public override void PerformUniqueAbility()
{
// class specific code here
}
public override void PerformUniqueBroadcastingAbility()
{
// class specific code here
}
}
Of course I cannot do this because of the error:
Error CS1721 Class 'MyNewClass' cannot have multiple base classes: 'Vehicle' and 'RadioSignalBroadcaster'
What's the best way to approach these scenarios?
You could use interfaces with default implementations which were introduced in C# 8. Then you could derive from these interfaces.
Here's an example of how you could you provide default implementations for the MoveForward() and StartBroadcast() methods:
public interface IVehicle
{
void MoveForward()
{
// your code
}
void PerformUniqueAbility();
}
public interface IRadioSignalBroadcaster
{
void StartBroadcast()
{
// your code
}
void PerformUniqueBroadcastingAbility();
}
You can't inherit more than 1 class but you can inherit more than one interface. Is this what you are looking for?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp3
{
internal class Program
{
static void Main(string[] args)
{
IVehicle vehicle = new Vehicle();
IRadioBroadcaster broadcaster = new RadioBroadcaster();
vehicle.MoveForward();
vehicle.PerformUniqueAbility();
broadcaster.StartBroadcast();
broadcaster.PerformUniqueAbility();
}
}
public interface IUniqueAbillity
{
void PerformUniqueAbility();
}
public interface IVehicle: IUniqueAbillity
{
void MoveForward();
}
public interface IRadioBroadcaster : IUniqueAbillity
{
void StartBroadcast();
}
public abstract class RealWorldObject : IVehicle, IRadioBroadcaster
{
public void MoveForward()
{
// Move forward
}
public abstract void PerformUniqueAbility();
public void StartBroadcast()
{
// Start broadcast
}
}
public class Vehicle : RealWorldObject, IVehicle
{
public override void PerformUniqueAbility()
{
// Do something
}
}
public class RadioBroadcaster : RealWorldObject, IRadioBroadcaster
{
public override void PerformUniqueAbility()
{
// Do something
}
}
}
C# classes can only inherit from one base class, but can inherit from any number of interfaces.
If your goal is to have multiple base classes being inherited to MyNewClass, you could change one of your abstract classes to inherit from the other, for example:
public abstract class RadioSignalBroadcast : Vehicle
{
// Implementation goes here
}
public class MyNewClass : RadioSignalBroacast
{
// Implementation goes here
}
However, as you can see from this approach, it violates Single Responsibility Principle as now RadioSignalBroadcast (and now MyNewClass) has more than one reason to change (if there's a change to Vehicle or RadioSignalBroadcast logic). Any change that happens to any of the base classes will propagate to all other classes which inherit from those base classes, which may or may not be what you're after.
What's the best way to approach these scenarios?
That entirely depends on the design of your application. Questions to ask yourself:
Do you require Vehicle and RadioSignalBroadcast to be abstract classes, or can it easily be an interface? By the looks of your implementation, you have a couple of methods which you want to share to your derived classes so I understand you wanting to keep them as base classes, but it's something to keep in mind. Also check out if the implementation of MoveForward and StartBroadcast can have a default interface implementation.
Does MyNewClass need to implement both base classes/interfaces? Couldn't two separate classes work out better? Separating out classes like this helps to focus each of the classes to have one single responsibility.
If MyNewClass is not truly a Vehicle or a RadioSignalBroadcast (as per the previous point), can this object be composed by a combination of either of the two, for example:
public class MyNewClass : Vehicle
{
private readonly RadioSignalBroadcast radio;
public MyNewClass(RadioSignalBroadcast radio)
{
this.radio = radio;
}
public void DoStuff()
{
// Do Stuff
this.radio.PerformUniqueBroadcastingAbility();
}
// Implementation goes here
}
Let me know if you want example or more points to point out.
I think Jonas gave you the best answer that you can use default interface implementations. However I keep my post, because it gives information, how to achieve same effect, using technology without this language feature.
public abstract class Example : IExample
{
private readonly IVehicle vehicle;
private readonly IRadioSignalBroadcaster;
public Example(IVehicle vehicle, IRadioSignalBroadcaster radioSignalBroadcaster)
{
this.vehicle = vehicle;
this.radioSignalBroadcaster = radioSignalBroadcaster;
}
public void MoveForward() => vehicle.MoveForward();
public void StartBroadcast() => radioSignalBroadcaster.StartBroadcast();
public void PerformUniqueAbility() => vehicle.PerformUniqueAbility();
public void PerformUniqueBroadcastingAbility() => radioSignalBroadcaster.PerformUniqueBroadcastingAbility();
}
public interface IExample : IVehicle, IRadioSignalBroadcaster
{
}
public interface IVehicle
{
void MoveForward();
void PerformUniqueAbility();
}
public interface IRadioSignalBroadcaster
{
void StartBroadcast();
void PerformUniqueBroadcastingAbility();
}
public abstract class Vehicle : IVehicle
{
public void MoveForward()
{
// ...
}
public abstract void PerformUniqueAbility();
}
public interface ICustomVehicle : IVehicle
{
}
public class CustomVehicle : Vehicle, ICustomVehicle
{
public void PerformUniqueAbility()
{
// ...
}
}
public abstract class RadioSignalBroadcaster : IRadioSignalBroadcaster
{
public void StartBroadcast()
{
// ...
}
public abstract void PerformUniqueBroadcastingAbility();
}
public interface ICustomRadioSignalBroadcaster : IRadioSignalBroadcaster
{
}
public class CustomRadioSignalBroadcaster : RadioSignalBroadcaster, ICustomRadioSignalBroadcaster
{
public void PerformUniqueBroadcastingAbility()
{
// ...
}
}
You will create another classes like that:
public class CustomExample : Example, ICustomExample
{
public CustomExample(ICustomVehicle customVehicle, ICustomRadioSignalBroadcaster customRadioSignalBroadcaster) : base(customVehicle, customRadioSignalBroadcaster)
{
}
}
public interface ICustomExample : IExample
{
}
I've previously seen a good solution to the issue of testing against interfaces, whereby you create an abstract test class for the interface, then inherit from that for the test for each class which derives from that interface, using a CreateInstance method to provide an instance of the given class. e.g.
public interface INamable {string Name{get;}}
[TestClass]
public abstract class INamableTests
{
protected abstract INamable CreateInstance(string name);
[TestMethod]
public void NameCorrectlyAssignedTest()
{
var expected = "this is my name";
var instance = CreateInstance(expected);
Assert.AreEqual(expected, instance.Name);
}
}
However, whilst the above approach works well when our class only implements one interface, things get a bit more complicated when multiple interfaces are inherited. We can get around this by having multiple test classes inherit from each abstract test class for each interface; but that solution only works for one level of inheritence. i.e. If we have another subclass in our inheritance hierarchy we need to repeat ourselves / don't get the benefit of the tests written for our base class.
To demonstrate, if we add the code at the end of this question to the above, we'd want to test:
INamable \
IStartable |- IBatchJob - BatchJob - AutoStopBatchJob
IStoppable /
But since we can't inherit from multiple classes, our test inheritance is limited to:
INamableTests - IBatchJobTests - BatchJobTests - AutoStopBatchJobTests
So to run IStartableTests and IStoppableTests for BatchJob and AutoStopBatchJob (and any other class using the IBatchJob interface) we need to repeat the code for calling those tests.
Is there a better approach for this?
public interface IStartable {void Start();bool IsRunning{get;}}
public interface IStoppable {void Stop();bool IsRunning{get;}}
public interface IBatchJob: INamable, IStartable, IStoppable {}
public class BatchJob: IBatchJob
{
public string Name {get; private set;}
public bool IsRunning {get; private set;}
public BatchJob(string name) {Name = name;}
public void Start() {IsRunning = true;}
public void Stop() {IsRunning = false;}
}
public class AutoStopBatchJob: BatchJob
{
System.Timers.Timer batchTimer;
public AutoStopBatchJob(string name, TimeSpan maxRunTime): base (name)
{
batchTimer = new System.Timers.Timer();
batchTimer.AutoReset = false;
batchTimer.Interval = maxRunTime.TotalMilliseconds;
batchTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
}
public override void Start()
{
base.Start();
batchTimer.Start();
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
Stop();
}
}
[TestClass]
public abstract class IStartableTests
{
protected abstract IStartable CreateInstance();
[TestMethod]
public void StartSetsRunningToTrue()
{
var instance = CreateInstance();
Assert.AreEqual(false, instance.IsRunning);
instance.Start();
Assert.AreEqual(true, instance.IsRunning);
}
}
[TestClass]
public abstract class IBatchJobTests: INamableTests
{
public abstract IBatchJob CreateInstance(string name);
//I've extended INamablTests, so those will get run.
//However, how should I test IStartable and IStoppable?
}
[TestClass]
public class BatchJobTests: IBatchJobTests
{
public static BatchJob CreateInstance(string name) => new BatchJob(name);
public IBatchJob CreateInstance(string name) => BatchJobTests.CreateInstance(name);
//do I have to implement nested classes for these interfaces for every derived class?
[TestClass]
public class BaseClassIStartableTests : IStartableTests
{
protected IStartable CreateInstance() => BatchJobTests.CreateInstance("Default Name");
}
[TestClass]
public class BaseClassIStoppableTests : IStoppableTests
{
protected IStoppable CreateInstance() => BatchJobTests.CreateInstance("Default Name", initialRunningState:=true);
}
}
I'm trying to remove the redundancy I have in my Enemy0, Enemy1, ... classes that inherit from my abstract Enemy class. This is all Monogame/XNA.
My abstract class looks like so:
public abstract class Enemy
{
public abstract Vector2 Position { get; }
public Enemy() {}
public abstract void Update(GameTime gameTime);
public abstract void Draw(SpriteBatch spriteBatch);
public abstract Part getLeftPart();
public abstract Part getRightPart();
public abstract Part getLeftLeftPart(); //This method only used in Boss0 classes
public abstract Part getRightRightPart(); //This method only used in Boss0 classes
}
Though my Enemy# classes vary in implementation, some methods are exactly the same/redundant and take up room (but have parameters relative to that class, eg the private variable _leftPartPos).
The problem occurs when I have 20 or so Enemy# classes and I decide to add an extra parameter to the Part object (which is used in getLeftPart()- I would have to also modify 20 of those classes that inherit the Enemy
public class Enemy0 : Enemy
{
private Texture2D _partTexture;
private Vector2 _leftpartPos;
private Vector2 _rightPartPos;
public override Vector2 Position
{
get { return _position; } // Reason for this get is to access inner variables
} // like _position.X = 10
private Vector2 _position;
public Enemy() {}
public abstract void Update(GameTime gameTime)
{
// Some varying functionality per inheriting class
}
public abstract void Draw(SpriteBatch spriteBatch)
{
// Some varying functionality per inheriting class
}
public override Part getLeftPart() // This always returns the same object (with
{ // different params)
return new Part(
_partTexture,
_leftPartPos,
SpriteEffects.FlipHorizontally);
}
public abstract Part getRightPart()
{
return new Part(
_partTexture,
_rightPartPos,
SpriteEffects.None);
}
public override Part getLeftLeftPart()
{
return null; // This only returns an instance in Boss0, Boss1, etc
}
public override Part getRightRightPart()
{
return null;
}
}
The reason I have this abstract class is so that I can initialize a List<Enemy> object and access its varied methods without having to cast each class as Enemy0, Enemy1, ...
Is there a way I can throw in the functionality of getLeftPart(), getRightPart(), ... into my abstract class? Is there a better approach for all this?
Declare them as virtual instead of abstract. That way you can provide a base implementation in the root class and override it in the child classes if they require different functionality.
public abstract class RootClass
{
public virtual void DoSomething()
{
Console.WriteLine("I'm doing something in the root class");
}
}
public class ChildClass1 : RootClass
{
public void SomethingElse()
{
DoSomething(); //Prints out "I'm doing something in the root class"
}
}
public class ChildClass2 : RootClass
{
public void SomethingElse()
{
DoSomething(); //Prints out "I'm doing something in ChildClass2
}
public override void DoSomething()
{
Console.WriteLine("I'm doing something in ChildClass2");
}
}
If you have to take variable numbers of parameters, declare the method with the params attribute, like:
public virtual void DoSomething(params object[] args)
This causes boxing, so be aware of the performance implications. If you need to do something more specific, try:
public virtual void DoSomething<T>(params T[] args)
But the only difference here is that all the parameters must be of the same type, or convertible to that type. If you only need one parameter of some type, use:
public virtual void DoSomething<T>(T arg)
or you can have two (or more types)
public virtual void DoSomething<T1, T2>(T1 arg1, T2 arg2)
etc, etc.
How can a variant of the Template Method pattern be implemented whereby the concrete class does not inherit from the base class, but the overall feature of the pattern is maintained. The reason it cannot inherit is that it's forced to inherit from another class and multiple-inheritance is unavailable.
For example, suppose the following Tempate Method pattern:
public abstract class BaseClass {
public void Alpha() {
Beta();
}
public abstract void Beta();
public void Gamma() {
Delta();
}
public abstract void Delta();
}
public ConcreteClass : BaseClass {
public override void Beta() {
Gamma();
}
public override void Delta() {
Console.WriteLine("Delta");
}
}
...
var object = new ConcreteClass();
object.Alpha(); // will outout "Delta"
How can I achieve the same result without ConcreteClass inheriting BaseClass?
Your base class could depend on an interface (or other type) that's injected via the constructor. Your template method(s) could then use the methods on this interface/type to achieve the pattern's desired outcome:
public class BaseClass
{
IDependent _dependent;
public BaseClass(IDependent dependent)
{
_dependent = dependent;
}
public void Alpha() {
_depdendent.Beta();
}
public void Gamma() {
_depdendent.Delta();
}
}
Effectively using composition rather than inheritance.
You can achieve this by providing a reference to the base class on method call:
public ConcreteClass {
public void Beta(BaseClass baseClass) {
baseClass.Gamma();
}
public void Delta() {
Console.WriteLine("Delta");
}
}
using System;
public class Base
{
public Base()
{
}
public void M1()
{
}
public void M2()
{
}
public void M3()
{
}
}
public class Derived : Base
{
//this class should get only method 1
}
public class SecondDerived : Base
{
//this class should get only method 2 and method3
}
The requirement is : the base class contains the 3 methods M1, M2, M3.
The derived class should inherit only M1 and SecondDerived should inherit only M2 and M3.
How can this be done?
You cannot selectively inherit methods like this. A derived class automatically inherits all public methods of the base class. I suggest you to split the Base class into two classes:
public class Base1
{
public Base1()
{
}
public void M1()
{
}
}
public class Base2
{
public void M2()
{
}
public void M3()
{
}
}
public class First : Base1
public class Second : Base2
You cannot do it in this way. Inheritance implies an "IS A" relationship.
If SecondDerived would not have a M1() then it would not be compatible with a reference to a the class Base.
So maybe you shouldn't be using inheritance for whatever problem you're solving.
It is not possible to do what you want with inheritance.
It seems you have no intention of overriding, you simply want to "inherit" behavior from the base class selectively. You could do this using a "has a" relationship:
public class Base
{
internal Base() {} //mark constructor as internal so it can not be used outside your assembly if necessary
public Foo Mehtod1() {...}
public Foo Mehtod2() {...}
public Foo Mehtod3() {...}
}
Then simply do the following:
class A
{
private Base internalBase;
public A() { this.internalBase = new Base(); }
public Foo Method1() { return this.internalBase.Method1(); }
}
class B
{
private Base internalBase;
public A() { this.internalBase = new Base(); }
public Foo Method2() { return this.internalBase.Method2(); }
public Foo Method3() { return this.internalBase.Method3(); }
}
UPDATE: A possible alternative solution is to make your Base class methods virtual and override them all in your derived classes, throwing NotSupportedExceptions in those methods that you do not want the class to make available. I don't really like this solution but it has the advantage of not loosing the polyphormism inheritance gives you which might be useful if you have some core base functionality which all derived classes will share (in your example you seem to imply they wont).
It is possible by adding Obsolete attribute
public class A
{
public virtual void M1() { }
public void M2() { }
public void M3() { }
}
public class B : A
{
[Obsolete("You can not use this", true)]
public sealed override void M1()
{
}
}
public class C : B
{
public void Test()
{
// Will show error
base.M1();
}
}