c# 8 Inheritance (with override) combined with default interface implementation - c#

I have an "inheritance-tree" which looks like this:
There is common code for the "TargetWithTeststand" and i would like to have a common code source. My only idea would be to use a separate static class and gather the methods which are common.
Another idea was to use a common interface with default methods, but this does not support override.
Do you have any better idea how to deal with such inheritance problems?
Here is a code example:
using System;
public class Program
{
public static void Main()
{
int deviceType = 1; // This value is read from a config file which can be changed
Device device = null;
switch (deviceType)
{
case 0:
device = new TargetWithTeststandDev1();
break;
case 1:
device = new TargetWithSimulationDev2();
break;
// [....]
}
device.ReadMotorSpeed();
device.UsePowerButton();
}
}
public abstract class Device
{
public virtual void UsePowerButton()
{
throw new NotImplementedException();
}
public virtual void ReadMotorSpeed()
{
throw new NotImplementedException();
}
}
public abstract class DeviceType1 : Device
{
public override void ReadMotorSpeed()
{
Console.WriteLine("Read motor speed with DeviceType1");
}
}
public abstract class DeviceType2 : Device
{
public override void ReadMotorSpeed()
{
Console.WriteLine("Read motor speed with DeviceType2");
}
}
public sealed class TargetWithTeststandDev1 : DeviceType1
{
public override void UsePowerButton()
{
Console.WriteLine("UsePowerButton on teststand with DeviceType1");
}
}
public sealed class TargetWithSimulationDev1 : DeviceType1
{
public override void UsePowerButton()
{
Console.WriteLine("UsePowerButton on teststand with DeviceType1");
}
}
public sealed class TargetWithTargetDev1 : DeviceType1
{
public override void UsePowerButton()
{
Console.WriteLine("UsePowerButton on Target with DeviceType1");
}
}
public sealed class TargetWithTeststandDev2 : DeviceType2
{
public override void UsePowerButton()
{
Console.WriteLine("UsePowerButton on Simulation with DeviceType2");
}
}
public sealed class TargetWithSimulationDev2 : DeviceType2
{
public override void UsePowerButton()
{
Console.WriteLine("UsePowerButton on Simulation with DeviceType2");
}
}
public sealed class TargetWithTargetDev2 : DeviceType2
{
public override void UsePowerButton()
{
Console.WriteLine("UsePowerButton on Target with DeviceType2");
}
}

You have literally drawn the diamond problem, One of the main reasons multiple inheritance is not supported.
The typical solution to this is to use composition instead of inheritance. I.e. gather all the common functions for a simulation in a separate class, that your SimulationDev1 and SimulationDev2 classes refer to, and any simulation operations would be delegated to this class.
An alternative would be to use interfaces and extension methods or default interface implementations to do more or less the same thing:
public interface ISimulation
{
int AProperty { get; }
}
public static class SimulationExtensions
{
public static int SomeCommonMethod(this ISimulation self, int b) => self.AProperty + b;
}

Related

What interface type is suited for implementing strategy with different signature?

consider the following game code:
public class Player : MonoBehaviour {
public void UseItem(Item item) {
item.Use(this);
}
public void GetDrunk() {}
}
public class Item {
public WhatInterface[] itemUsages;
public void Use(Player player) {
foreach(var usage in itemUsages) {
usage.Execute(new ItemUsageArgs {itemUser = player, itemUsed = this})
}
}
}
public class GameManager : MonoBehaviour {
public Player mainCharacter;
public Item beer = new Item {itemUsages = new [] {
new TestConsole(),
new DamageFromItem (),
new DrunkFromITem ()
}}
private void Start() {
mainCharacter.Use(beer);
}
}
public class TestConsole : WhatInterface {
public void Execute(BaseArgs args) {
Debug.Log("function call executed");
}
}
public class DamageFromItem : WhatInterface {
public void Execute(ItemUsageArgs args) {
Debug.Log(args.itemUser + " take damage from " + args.itemUsed);
}
}
public class DrunkFromITem : WhatInterface {
public void Execute(ItemUsageArgs args) {
args.itemUser.GetDrunk();
}
}
public class BaseArgs {}
public class ItemUsageArgs : BaseArgs {
public Player itemUser;
public Item itemUsed;
}
so how to create interface type code that is suited for itemUsages?
Or do I wrongly create the design for this context?
Basically I'm trying strategy pattern so that item usages could be vary for every kind of item.
Things I tried, creating IItemUsage interface:
public interface IItemUsage {
void Execute(ItemUsageArgs args);
// but then anything that needs to implement this interface must use this method, even though it only needs BaseArgs.
// TestConsole class must conform to Execute(ItemUsageArgs) signature..
}
public class TestConsole : IItemUsage {
public void Execute(BaseArgs args) {
Debug.Log("function call executed");
}
// this won't compile
}
Assuming this is all of your code, you can make IItemUsage generic, and contravairant on the generic parameter.
public interface IItemUsage<in T> where T: BaseArgs {
void Execute(T args);
}
Have TestConsole implement IItemUsage<BaseArgs> and the other two classes implement IItemUsage<ItemUsageArgs>.
Now you can put instances of all three classes into an IItemUsage<ItemUsageArgs>[]:
IItemUsage<ItemUsageArgs>[] arr = new IItemUsage<ItemUsageArgs>[] {
new TestConsole(), new DamageFromItem(), new DrunkFromITem()
};
If you want to implement interface with some method, which has input arguments, that can be different types, you must define base argument class or use interface parameter instead.
For example:
public interface IItemUsage
{
void Execute(IItemUsageArgs args);
}
public interface IItemUsageArgs
{
//place public part of all ItemUsageArgs
}
public class ItemUsageArgs1 : IItemUsageArgs
{
}
public class ItemUsageArgs2 : IItemUsageArgs
{
}
public class ItemUsage1 :IItemUsage
{
public void Execute(ItemUsageArgs1 args)
{
//do you need
}
void IItemUsage.Execute(IItemUsageArgs args)
{
Execute(args as ItemUsageArgs1);
}
}
public class ItemUsage2 : IItemUsage
{
public void Execute(ItemUsageArgs2 args)
{
//do you need
}
void IItemUsage.Execute(IItemUsageArgs args)
{
Execute(args as ItemUsageArgs2);
}
}

How to make subclasses automatically call superclass methods

I'm a new developer of c# and I'm using unity3d to develop a game.
I design an interface to implement the skill system in game. But I find some trouble. Here are a lot of Skill classes, and I must call show() method manually inside their apply.
interface ISkill
{
void apply();
}
class Base
{
protected string name { get; set; }
protected void show()
{
Console.WriteLine("show:"+name);
}
}
class Skill1 : Base, ISkill
{
public Skill1()
{
name = "skill1";
}
public void apply()
{
show();
Console.WriteLine("skill1 apply");
}
}
class Skill2 : Base, ISkill
{
public Skill2()
{
name = "skill2";
}
public void apply()
{
show();
Console.WriteLine("skill2 apply");
}
}
Skill3
Skill4
etc..
class Program
{
public static void Main(string[] args)
{
ISkill skill = new Skill2();
skill.apply();
}
}
How to modify my code so that the all SkillX classes can automatically call show() method in apply() method?
Standard solution for this is template method.
Base class implements method as "template" that forces derived classes to provide particular step(s) for that method. In your case the Base class should implement Apply method that calls Show first and than delegates the rest to derived classes by forcing them to provide implementation of the second part via abstract void ApplyImplementation():
interface ISkill
{
void Apply();
}
public abstract class Base
{
protected string name { get; set; }
protected Base(string name)
{
this.name = name;
}
protected void Show()
{
Console.WriteLine("show:"+name);
}
// "template" method.
public void Apply()
{
Show();
ApplyImplementation();
}
// derived class must implement that method
protected abstract void ApplyImplementation();
}
class Skill1 : Base, ISkill
{
public Skill1()
{
name = "skill1";
}
protected override void ApplyImplementation()
{
Console.WriteLine("skill1 apply");
}
}
No general solution, other than trying to pull the commonality across different classes to the base.
In your case, since the only differences among the apply() seems to be the skill name, and you already have it as an instance property, you can pull the apply up to the Base, and have the same implementation across all the child classes of Base.
interface ISkill
{
void apply();
}
class Base : ISkill
{
protected string name { get; set; }
protected Base(string name)
{
this.name = name;
}
public void apply()
{
show();
Console.WriteLine(name + " apply");
}
private void show()
{
Console.WriteLine("show:"+name);
}
}
class Skill1 : Base
{
public Skill1(): base("skill1"){}
}
class Skill2 : Base
{
public Skill2(): base("skill2"){}
}

Can I eliminate duplicate code for below derived classes and move to abstract base class

I have a abstract base class, starting a timer which is common to all derived class,
public abstract class BaseClass
{
public virtual void Start() { _timer.Start(); }
}
Now I need to load different JSON configuration files for each derived class and create the file,
public class DerivedClass1 : BaseClass
{
private readonly List<config> configs = new List<config>();
public DerivedClass1()
{
configs = JsonSettings.GetConfigurations(#"./Configurations/1.json");
}
public override void Start()
{
base.Start();
foreach (var configuration in configs)
{
JsonSettings.CreateConfigFile(configuration);
}
}
}
public class DerivedClass2 : BaseClass
{
private readonly List<config> configs = new List<config>();
public DerivedClass2()
{
configs = JsonSettings.GetConfigurations(#"./Configurations/2.json");
}
public override void Start()
{
base.Start();
foreach (var configuration in configs)
{
JsonSettings.CreateConfigFile(configuration);
}
}
}
As I see there are lots of codes are duplicated in various derived class.
Can I move these piece of code as well as abstract base class or is there another way?
I think you could simplify your code to this:
public abstract class BaseClass
{
protected virtual List<config> configs { get; set; } = new List<config>();
public virtual void Start()
{
_timer.Start();
foreach (var configuration in configs)
{
JsonSettings.CreateConfigFile(configuration);
}
}
}
public class DerivedClass1 : BaseClass
{
public DerivedClass1()
{
configs = JsonSettings.GetConfigurations(#"./Configurations/1.json");
}
}
public class DerivedClass2 : BaseClass
{
public DerivedClass2()
{
configs = JsonSettings.GetConfigurations(#"./Configurations/2.json");
}
}
public interface BaseClass
{
void Start();
}
public interface IBaseClassUtil
{
void Start();
void setConfigs(List<config> configs);
}
public class BaseClassUtil : IBaseClassUtil
{
System.Timers.Timer _timer;
public List<config> _configs { get; set; } = new List<config>();
public void Start()
{
_timer.Start();
foreach (var configuration in _configs)
{
JsonSettings.CreateConfigFile(configuration);
}
}
public void setConfigs(List<config> configs)
{
_configs = configs;
}
}
public class DerivedClass1 : BaseClass
{
private IBaseClassUtil _baseUtility;
public DerivedClass1(IBaseClassUtil baseUtility)
{
_baseUtility = baseUtility;
_baseUtility.setConfigs( JsonSettings.GetConfigurations(#"./Configurations/1.json"));
}
public void Start()
{
_baseUtility.Start();
}
}
public class DerivedClass2 : BaseClass
{
private IBaseClassUtil _baseUtility;
public DerivedClass2(IBaseClassUtil baseUtility)
{
_baseUtility = baseUtility;
_baseUtility.setConfigs(JsonSettings.GetConfigurations(#"./Configurations/2.json"));
}
public void Start()
{
_baseUtility.Start();
}
}
This might be oveer engineered. Or might not suit ur current requirement.
Advantages would be
In future if you want u want to have different implementation for IBaseClassUtil it will be easier
And huge advantage would be this code is testable
If the classes differ by nothing but the configuration path, then you can have only one derived class that takes the path as a parameter in its ctor.
public DerivedClass(string configurationPath)
{
configs = JsonSettings.GetConfigurations(configurationPath);
}
Put please note that a decision on including inheritance in your architecture is not about code duplication, and by not giving us any information on the functions or even names of the classes (BaseClass and DerivedClass mean nothing. What do they represent? What's their function? Why are they related?) you give us no way of really helping you with your design.

Abstract and virtual functions

I am trying to implement two level inheritance. Currently, there is an abstract class and an inherited class :
public abstract class A
{
public abstract void func();
}
public class B : A
{
public override void func()
{
.......
}
}
I would like to create two specialized instances of class B but I want those functions to be exposed by class A. I am going for,
public abstract class A
{
public abstract void func();
}
public class B : A
{
public virtual void func();
}
public class C : B
{
public override void func()
{
........
}
}
public class D : B
{
public override void func()
{
........
}
}
This implementation is wrong but that is my intent. How will I implement this ?
You can use interface instead of abstract class A like this:
public interface A
{
void func();
}
public abstract class B: A
{
public abstract void func();
}
public class C : B
{
public override void func()
{
throw new NotImplementedException();
}
}
public class D : B
{
public override void func()
{
throw new NotImplementedException();
}
}
May be it helps you.
You cannot have virtual method without implementation, so instead you should make class B abstract, which should make compiler happy:
public abstract class B : A
{
}
Alternative approach is to add empty method body for function func:
public class B : A
{
public virtual void func()
{
// function has empty method body
// it does not do anything, but you can override functionality in derived classes
}
}

Inheriting a generic in c#

I've inherited a large codebase and I'm trying to implement some new functionality into the framework. Basically, in order to do it the "right" way, I would have to modify the entire structure of the framework. since I'm not the guy who designed the framework, nor am I a mind reader, doing so probably isn't going to happen (although I would really love to redesign it all from scratch myself).
So in order to do what I want, I'm trying to implement a decorator pattern, of sorts. This answer from maliger suggests that what I'm doing below is perfectly valid. However, mono doesn't seem to like it; it complains that T cannot be derived from when I declare HappyDecorator
Please forgive the overly simplistic example, but it gets the point across.
public class HappyObject
{
public virtual void print()
{
Console.WriteLine ("I'm happy");
}
}
public class VeryHappyObject : HappyObject
{
public override void print()
{
Console.WriteLine ("I'm very happy");
}
public void LeapForJoy()
{
Console.WriteLine("Leaping For Joy!");
}
}
public class SuperHappyObject : VeryHappyObject
{
public override void print()
{
Console.WriteLine ("I'm super happy!");
}
public void DieOfLaughter()
{
Console.WriteLine("Me Dead!");
}
}
public class HappyDecorator<T> : T where T : HappyObject
{
public string SpecialFactor { get; set; }
public void printMe()
{
Console.WriteLine (SpecialFactor);
print();
}
}
class MainClass
{
public static void Main (string[] args)
{
HappyDecorator<HappyObject> obj = new HappyDecorator<HappyObject> ();
obj.SpecialFactor = Console.ReadLine();
obj.printMe();
}
}
You're typing HappyDecorator to T, but there's no instance of T to use inside that class.
public class HappyDecorator<T> where T : HappyObject
{
private readonly T _instance;
public HappyDecorator(T instance)
{
_instance = instance;
}
public string SpecialFactor { get; set; }
public void printMe()
{
Console.WriteLine(SpecialFactor);
_instance.print();
}
}
Another alternative is to structure it like this with a generic method instead of a generic class. It's not really a decorator then though:
public class HappyDecorator
{
public string SpecialFactor { get; set; }
public void printMe<T>(T instance) where T : HappyObject
{
Console.WriteLine(SpecialFactor);
instance.print();
}
}
And call like:
HappyDecorator obj = new HappyDecorator();
obj.SpecialFactor = Console.ReadLine();
obj.printMe(new HappyObject());
I think this is what you are trying to do:
public interface IhappyObject
{
void Print();
}
public class HappyObject : IhappyObject
{
private IhappyObject obj;
public HappyObject(IhappyObject obj)
{
this.obj = obj;
}
public void Print()
{
obj.Print();
}
}
public class VeryHappyObject : IhappyObject
{
public void Print()
{
Console.WriteLine("I'm very happy");
}
}
public class SuperHappyObject : IhappyObject
{
public void Print()
{
Console.WriteLine("I'm super happy!");
}
}
static void Main(string[] args)
{
HappyObject obj = new HappyObject(new SuperHappyObject());
obj.Print();
}

Categories