I try to achieve the following: I have an interace called IAxis that forces my class TheAxis to have certain methods. In addition I want to implement some kind of abstract class based on a parameter. To explain this will write it down in code:
class TheAxis : IAxis
{
public TheAxis(){ }
public void IMoveToPos(int pos) {} //This is forced by the Interface
}
As the instance of this class is called it should be able to choose which methods to include, similar to virtual methods but not overriding existing methods but adding already coded ones from another class. I am looking for something like this:
abstract class GateAxis
{
public void CloseGate() { IMoveToPos(0); }
}
abstract class XAxis
{
public void MoveToStart() { IMoveToPos(100); }
}
TheGateAxis = new Axis() as GateAxis;
Now I want to be able to use TheGateAxis.Closegate(); but NOT TheGateAxis.MoveToStart();
if I call
TheXAxis = new Axis() as XAxis;
I want to be able to use TheXAxis.MoveToStart(); but NOT TheXAxis.CloseGate();
The Methods Given in XAxis or GateAxis donĀ“t need any methods from TheAxis except the onces given by the interface.
Is it possible to do somethign like that? To add Methods to a class depending on a parameter given while instancing the class?
I hope you get what I am trying to do as I do hard to explain.
Best,
Kevin
Well, if you want classes sharing few methods from a base class, and other being separate, you could do
//an interface (optional)
public interface IAxis {
void MoveToPos(int pos);
}
public abstract class AxisBase : IAxis {
public void MoveToPos(int pos) {
//implementation
}
}
//optionally you can do an IGateAxis interface, inheriting (or not) from IAxis
public interface IGateAxis : IAxis {
void CloseGate();
}
//classes inheriting from AxisBase, implementing IGateAxis
public class GateAxis : AxisBase, IGateAxis {
public void CloseGate() {
MoveToPos(0);
}
}
//another interface, not inheriting from IAxis
public interface IXAxis {
void MoveToStart();
}
//another class inheriting from AxisBase
public class XAxis : AxisBase, IXAxis {
public void MoveToStart() {
MoveToPos(100);
}
}
usage
var gateAxis = new GateAxis();
gateAxis.CloseGate();
//and you can do
gateAxis.MoveToPos(250);
var xAxis = new XAxis();
xAxis.MoveToStart();
//and you can do
xAxis.MoveToPos(40);
with the IGateAxis interface
IGateAxis gateAxis = new GateAxis();
gateAxis.CloseGate();
gateAxis.MoveToPos(1);
with the IXAxis interface
IXAxis xAxis = new XAxis();
gateAxis.MoveToStart();
//but you can't do
//gateAxis.MoveToPos(10);
//as IXAxis doesn't know about this method.
// super class
abstract class TheAxis : IAxis {
public TheAxis() { }
public void IMoveToPos(int pos) { } //This is forced by the Interface
}
abstract class GateAxis : TheAxis {
public virtual void CloseGate() { IMoveToPos(0); }
}
abstract class XAxis : TheAxis {
public virtual void MoveToStart() { IMoveToPos(100); }
}
Now if you derive a class from GateAxis it'll only have access to the interface methods and the methods from GateAxis. Same goes for TheAxis.
Dynamically adding methods, and removing them is not something that you can do in "normal" C# . There is no any OOP pattern that can simulate this.
What you can do, is using ExpandoObject to be able to achieve exactly what you're trying to achieve.
Represents an object whose members can be dynamically added and
removed at run time.
By the way I would not encourage of using it as you are in statical type language domain, so may be it's a godd idea to revise your architectiure a little bit and don't jump in dynamic language domain using C#.
I think the best way to solve this is to use interfaces and a single (base) class.
public interface IAxis {
void MoveToPos(int pos);
}
public interface IGateAxis {
void CloseGate();
}
public interface IXAxis {
void MoveToStart();
}
public class TheAxis : IAxis, IGateAxis, IXAxis {
public TheAxis(){ }
void IAxis.MoveToPos(int pos) {}
void IGateAxis.CloseGate() { ((IAxis)this).MoveToPos(0); }
void IXAxis.MoveToStart() { ((IAxis)this).MoveToPos(100); }
}
IGateAxis gateAxis = new ThisAxis();
gateAxis.CloseGate();
IXAxis xAxis = new ThisAxis();
xAxis.MoveToStart();
This way you can specify which methods are available to certain types of axis. Also, you could force the creation of axis through a factory pattern, or even a single static method, just to facilitate the creation of axis.
Assuming you have more than 3 methods, the easiest way that I see is to simply create a proxy that acts as a chain of responsibility:
public class AxisProxy : IAxis
{
public AxisProxy(params IAxis[] implementations) {
this.implementations = implementations;
}
private IAxis[] implementations;
public virtual void CloseGate()
{
foreach (var item in implementations)
{
try { item.CloseGate(); } catch (NotSupportedException) {}
}
throw new NotSupportedException();
}
public virtual void MoveToStart()
{
foreach (var item in implementations)
{
try { item.MoveToStart(); } catch (NotSupportedException) {}
}
throw new NotSupportedException();
}
}
You can create a base implementation of Axis to make sure all default implementations throw the exception. Derived implementations implement specific functionality.
You can then use it by simply calling
IAxis myAxis = new AxisProxy(new GateAxis(), new XAxis());
NOTE: In this case I would seriously consider changing the types to 'bool'; if you call these methods frequently, exception performance will add up... Also, since the NotSupportedException is not going to change, you can keep a per-method list to remove implementations that throw.
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
{
}
Is it possible to specify in a Unity Resolve which constructor Unity should use?
The object I am trying to create may look something like this:
public class MyObject
{
[UseWhenSunny]
public MyObject(InputOne one)
{
Console.WriteLine("Chose constructor one");
}
[UseWhenRaining]
public MyObject(InputTwo two)
{
Console.WriteLine("Chose constructor two");
}
}
public class InputOne
{
}
public class InputTwo
{
}
My construction could be something like this:
var container = new UnityContainer();
container.RegisterInstance(new InputTwo());
var myObject = container.Resolve<MyObject>();
I can find the correct ConstructorInfo easily enough, but I have not figured out how to force Unity to use this specific constructor?
It's a strange construct when you use different constructors for states within a game/program. If you want to pass two different class types, you could use inheritance for that. You need a common ancestor because InputOne and InputTwo only shares Object as common ancestor. So you need to specify a new base class. In this base class you write the common functionality/definition.
Here is an example:
public abstract class InputBase
{
public abstract void Show();
}
public class InputOne : InputBase
{
public override void Show()
{
Console.WriteLine("Show one");
}
}
public class InputTwo : InputBase
{
public override void Show()
{
Console.WriteLine("Show two");
}
}
public class MyObject
{
public MyObject(InputBase input)
{
// because InputOne and InputTwo can be casted to their base class
// they both can be passed as InputBase.
// InputBase defines the Show method which their derived ones must
// implement (abstract).
input.Show();
}
}
See Inheritance (C# Programming Guide)
During a recent interview I was asked to write a program that takes a list of different vehicles, or whatever, that implement a honk interface, use an abstract class, and then have a different honk for the different vehicles. This is what I came up with so far, and it works fine as long as I call the methods independently. But when I try to put them into an IEnumerable, and then iterate through, it displays the honk for the abstract class, not the individual classes. Can someone explain what I am doing wrong?
using System;
using System.Collections.Generic;
namespace ConsoleHonk
{
class Program
{
static void Main(string[] args)
{
var myList = GetVehicles();
//This doesn't display the correct honk
myList.ForEach(x => x.honk());
}
private static List<IHonker> GetVehicles()
{
var myList = new List<IHonker>();
var myTruck = new Truck();
var myCar = new Car();
var myGoose = new Goose();
myList.Add(myTruck);
myList.Add(myGoose);
myList.Add(myCar);
return myList;
}
}
class Goose : HonkClass
{
public virtual void honk()
{
Console.WriteLine("Quack");
}
}
class Car : HonkClass
{
}
class Truck:HonkClass
{
public virtual void honk()
{
Console.WriteLine("Honk-Honk");
}
}
interface IHonker
{
string horn { get; set; }
void honk();
}
public abstract class HonkClass:IHonker
{
public void honk()
{
Console.WriteLine("Beep");
}
public string horn { get; set; }
}
}
In this case you need an abstract base class because it's a requirement for your interview. However, generally in this situation, if you do not have that artificial constraint, you should not use a base class at all. You can just have the individual vehicles directly implement the interface.
In general you shouldn't use a base class without good reason. For one thing, C# supports implementing multiple interfaces but does not support multiple inheritance. So you can have a class implement both interfaces IHonkable and ISteerable, but not inherit from both classes HonkableBase and SteerableBase.
The problem with your code is that the Honk methods aren't overriding the abstract class's, they're hiding it. The difference in behaviour is exactly what you describe:
public class HidingVehicle : HonkClass
{
public void Honk()
{
Console.Writeline("Hiding honk!");
}
}
public class OverridingVehicle : HonkClass
{
public override void Honk()
{
Console.Writeline("Overriding honk!");
}
}
public class HonkClass
{
public virtual void Honk()
{
Console.Writeline("Base honk!");
}
}
Then a method might be:
var myHidingVehicle = new HidingVehicle();
var myOverridingVehicle = new OverridingVehicle();
myHidingVehicle.Honk(); //"Hiding honk!"
myOverridingVehicle.Honk(); //"Overriding honk!"
HonkClass hiddenVehicle = myHidingVehicle;
HonkClass overridenVehicle = myOverridingVehcile;
hiddenVehicle.Honk(); //"Base honk!"
overridenVehicle.Honk(); //"Overriding honk!"
As you can see from the code, the difference is in the overriding keyword.
Hiding can be deliberate, but it's very rarely desirable as it breaks polymorphism. If it you do want to hide, and you're sure there isn't a better option, you can use the new keyword in the method declaration to hide the compiler warning and make it clear to anyone reading the code that you're hiding.
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");
}
}
Let's say I have some basic interface which is generics-driven:
public interface Inteface<T> {
void Foo(T t);
}
Now I have some concrete implementation of this interface which is also generic:
public class InterfaceImpl<T> {
public void Foo(T t) {
// Whatever
}
}
This looks OK, but now let's say I have other class:
public class Ololo {
public void BadFunction<TShouldModelInterface>(TShouldModelInterface shouldModelInterface) {
// Whatever
}
}
And let's say I want to perform a check if TShouldModelInterface actually implements any of the possible Interface<T>.
If the interface wasn't generic, I would simply write something like where TShouldModelInterface : Interface.
But is there any way to solve this problem if the interface is a declared as Interface<T>?
public class Ololo {
public void BadFunction<TShouldModelInterface, T>(TShouldModelInterface shouldModelInterface)
where TShouldModelInterface : Interface<T>
{
// Whatever
}
}