Relationship between two interfaces and two classes. - c#

So I want to design a team/player relationship like this: every player belongs to one team but since I wanted to practice with interfaces I made ITeam and IAthlete and then made BasketballTeam and BasketballPlayer.
Then I wrote this code:
public interface IAthlete
{
string GetName();
string GetSport();
}
public interface ITeam
{
void AddPlayer(IAthlete player);
IAthlete[] GetAthletes();
string GetName();
int GetNumberOfPlayers();
}
public class BasketballPlayer:IAthlete
{
private string name;
public string GetName()
{
return this.name;
}
public string GetSport()
{
return "Basketball";
}
public BasketballPlayer(string name)
{
this.name = name;
}
public void Run(int distance)
{
Console.WriteLine(this.name + " just ran " + distance.ToString() + " meters.");
}
public bool Shoot()
{
Console.WriteLine("Successful shot for " + this.name);
return true;
}
}
public class BasketballTeam: ITeam
{
BasketballPlayer[] players;
int numberOfPlayers;
private string name;
public void AddPlayer(BasketballPlayer player)
{
this.players[this.numberOfPlayers] = player;
this.numberOfPlayers++;
}
public IAthlete[] GetAthletes()
{
return this.players;
}
public string GetName()
{
return this.name;
}
public int GetNumberOfPlayers()
{
return this.numberOfPlayers;
}
public BasketballTeam(string name)
{
this.numberOfPlayers = 0;
this.name = name;
this.players = new BasketballPlayer[10];
}
}
class Program
{
static void Main(string[] args)
{
BasketballTeam bt = new BasketballTeam("MyTeam");
BasketballPlayer bp = new BasketballPlayer("Bob");
bt.AddPlayer(bp);
foreach (BasketballPlayer player in bt.GetAthletes())
{
Console.WriteLine(player.GetName());
}
foreach (IAthlete a in bt.GetAthletes())
{
Console.WriteLine(a.GetName());
}
}
}
But it won't compile because I'm using this:
public void AddPlayer(BasketballPlayer player)
in the BasketballPlayer instead of this
public void AddPlayer(IAthlete player)
I thought it should work because BasketballPlayer is an IAthlete.
And if I change it to IAthlete then I can make another class like this:
public class HockeyPlayer : IAthlete
{
private string name;
public string GetName()
{
return this.name;
}
public string GetSport()
{
return "Hockey";
}
public HockeyPlayer(string name)
{
this.name = name;
}
public void Run(int distance)
{
Console.WriteLine(this.name + " just ran " + distance.ToString() + " meters.");
}
}
and then do this in my main:
HockeyPlayer hp = new HockeyPlayer("Henry");
bt.AddPlayer(hp);
which is logically wrong because I'm adding HockeyPlayer to a BasketballTeam. Is it supposed to be like this and I should just be careful not to do that? What am I doing wrong? How do I show this using class diagrams? Does this lead to loose coupling?

You're trying to violate the Liskov Substitution Principle.
Anything that can be done with a supertype – such as adding a HockeyPlayer – can also be done with a subtype – including a BasketballTeam.
Instead, you should use generics:
class Team<TPlayer> where TPlayer : IAthlete {
public ReadOnlyCollection<TPlayer> Players { get; }
public string Name { get; }
public void AddPlayer(TPlayer player);
}

Here is some thoughts on your code. First, in C# you can use properties, instead of Get and Set methods.
public interface IAthlete
{
string Name { get; }
string Sport { get; }
}
With auto-properties you can ask compiler to generate back store for property. Also consider creating base class Player, which will hold implementation of Name and Sport properties.
public class Player : IAthlete
{
public Player(string name, string sport)
{
Name = name;
Sport = sport;
}
public string Name { get; private set; }
public string Sport { get; private set; }
}
Now when implementing some player, you can just pass values to base class constructor. And your custom players will hold only specific for them functionality (no code duplication). Also it's recommended to use string format, instead of concatenating strings:
public class BasketballPlayer : Player
{
public BasketballPlayer(string name)
: base(name, "Basketball")
{
}
public void Run(int distance)
{
Console.WriteLine("{0} just ran {1} meters.", Name, distance);
}
public bool Shoot()
{
Console.WriteLine("Successful shot for " + Name);
return true;
}
}
Now about teams. If you don't want to have FootballPlayers in your BasketballTeam, then you should create parametrized team. Also consider using IEnumerable:
public interface ITeam<TPlayer>
where TPlayer : IAthlete
{
void AddPlayer(TPlayer player);
IEnumerable<TPlayer> Players { get; }
string Name { get; }
int NumberOfPlayers { get; }
}
Again, for common functionality you can create base class. Keep in mind, that you should check how many players currently in your team before adding new player.
public class Team<TPlayer> : ITeam<TPlayer>
where TPlayer : IAthlete
{
private readonly List<TPlayer> _players = new List<TPlayer>();
public Team(string name, int teamSize)
{
Name = name;
TeamSize = teamSize;
}
public void AddPlayer(TPlayer player)
{
if (_players.Count == TeamSize)
throw new Exception("Players number exceeded");
_players.Add(player);
}
public string Name { get; private set; }
public int TeamSize { get; private set; }
public IEnumerable<TPlayer> Players
{
get { return _players; }
}
public int NumberOfPlayers
{
get { return _players.Count; }
}
}
And custom team implementation becomes really easy. You just tell which type of players it will have, and pass to base team implementation team name and size of team.
public class BasketballTeam : Team<BasketballPlayer>
{
public BasketballTeam(string name)
: base(name, 10)
{
}
}
Now your program works like a charm:
class Program
{
static void Main(string[] args)
{
BasketballTeam bt = new BasketballTeam("MyTeam");
BasketballPlayer bp = new BasketballPlayer("Bob");
bt.AddPlayer(bp);
foreach (BasketballPlayer player in bt.Players)
{
Console.WriteLine(player.Name);
}
foreach (IAthlete a in bt.Players)
{
Console.WriteLine(a.Name);
}
}
}

Logically ,
These should be your base classes : Team , Player
These should be your derived classes : BasketballTeam , BasketballPalyer
These should be interfaces on Player : IPlay() , IRun , IGetName etc.. whichever applicable
and so on...
Guideline : Verbs suits more good on interfaces and Noun suits good on classes. Noun in the requirement best suits for Class in the code.

SLaks is correct. You could add a generic constraint to your ITeam to not accept all players, but just those of one type:
public interface ITeam<T> where T : IAthlete
{
void AddPlayer(T player);
IAthlete[] GetAthletes();
// or: T[] GetAthletes();
string GetName();
int GetNumberOfPlayers();
}
A BasketballTeam implementation could look like:
public class BasketballTeam : ITeam<BasketballPlayer>
{
BasketballPlayer[] players;
// […]
public void AddPlayer(BasketballPlayer player)
{
this.players[this.numberOfPlayers] = player;
this.numberOfPlayers++;
}
public IAthlete[] GetAthletes()
{
return this.players;
}
// or:
// public BasketballPlayer[] GetAthletes()
// {
// return this.players;
// }
// […]
}

If your interfaces are meant to be used by variety of games, it seems that you are missing the Game here and perhaps need to use Generics:
public interface IGame
{
string Name {get;}
...
}
public class Bastketball : IGame
{
...
}
public interface ITeam<TGame> where TGame: class, IGame
{
void AddPlayer(IPlayr<TGame> player);
...
}
public interface IPlayer<TGame> where TGame: class, IGame
{
...
}
This will prevent from hockey player to be added to Basketball team.

Related

Downcasting a List<AbstractClass> object to what the object actually is

I have a ParentClass. Two classes are inherit from it, FirstChildClass and SecondChildClass. A class MultipleValueTypes contains a Dictionary and a method that adds values to it. My intention is to be able to pass values of different classes, which inherit from the same abstract class to the value parameter of the Dictionary. Therefore, I initialize the dictionary with the value List<ParentClass> so that I would be able to add objects made with the child classes to the Dictionary. I can do this, but I cannot access them, therefore in the abstract class I create a way to tell them apart, a virtual method that both the children classes override to return their own class type.
I test the values they return against the enum itself and based on whether the condition is fulfilled, the object would be casted as what it is instead of a List<ParentClass>. Is this the wrong approach? Is this impossible?
I think it should work, because in my thinking the FirstObject and SecondObject are still objects of their respective classes, so casting should work and I should be able to access the overridden method.
What doesn't work: I cannot access the method that returns what type of class it is, because it only gets methods from the List<ParentClass>.
What I've tried so far: searching for a way to access the method, but I did not find any.
What I still need help with: everything mentioned above.
public abstract class ParentClass
{
public string Name { get; set; }
public ParentClass(string Name)
{
this.Name = Name;
}
public enum ChildClasses
{
NoChildClass = 0,
FirstChildClass = 1,
SecondChildClass = 2
}
public virtual ChildClasses TypeOfClass()
{
return ChildClasses.NoChildClass;
}
}
public class FirstChildClass : ParentClass
{
private string _randomvalue;
public string RandomValue { get => _randomvalue; set => _randomvalue = value; }
public FirstChildClass(string Name) : base(Name)
{
}
public void ReturnMessage()
{
Console.WriteLine("This is the FirstChildClass");
}
public override ChildClasses TypeOfClass()
{
return ChildClasses.FirstChildClass;
}
}
public class SecondChildClass : ParentClass
{
private string _randomvalue;
public string RandomValue { get => _randomvalue; set => _randomvalue = value; }
public SecondChildClass(string Name) : base(Name)
{
}
public void ReturnMessage()
{
Console.WriteLine("This is the SecondChildClass");
}
public override ChildClasses TypeOfClass()
{
return ChildClasses.SecondChildClass;
}
}
class MultipleValueTypes
{
public Dictionary<string, List<ParentClass>> ADictionary = new Dictionary<string, List<ParentClass>>();
public void AddObject(string Name, ParentClass variable)
{
if (!ADictionary.ContainsKey(Name))
{
ADictionary.Add(Name, new List<ParentClass>());
}
ADictionary[Name].Add(variable);
}
}
class Program
{
static void Main(string[] args)
{
FirstChildClass FirstObject = new FirstChildClass("FirstObject");
SecondChildClass SecondObject = new SecondChildClass("SecondObject");
MultipleValueTypes TestDictionary = new MultipleValueTypes();
TestDictionary.AddObject("FirstObject", FirstObject);
TestDictionary.AddObject("SecondObject", SecondObject);
if(TestDictionary.ADictionary["FirstObject"].TypeOfClass() == ParentClass.ChildClasses.FirstChildClass) ///List<ParentClass>' does not contain a definition for 'TypeOfClass' and no accessible extension method 'TypeOfClass' accepting a first argument of type 'List<ParentClass>' could be found (are you missing a using directive or an assembly reference?)
{
TestDictionary.ADictionary["FirstObject"] = (FirstChildClass)TestDictionary.ADictionary["FirstObject"]; ///Cannot convert type 'System.Collections.Generic.List<Dictionary.ParentClass>' to 'Dictionary.FirstChildClass
}
}
}
You forgot to use indexer of the list value of the key of the dictionary here:
==> TestDictionary.ADictionary["FirstObject"][0]
Here is your code now refactored too:
class Program
{
static void Main(string[] args)
{
var FirstObject = new FirstChildClass("FirstObject");
var SecondObject = new SecondChildClass("SecondObject");
FirstObject.ReturnMessage();
SecondObject.ReturnMessage();
MultipleValueTypes TestDictionary = new MultipleValueTypes();
TestDictionary.AddObject("FirstObject", FirstObject);
TestDictionary.AddObject("SecondObject", SecondObject);
if ( TestDictionary.ADictionary["FirstObject"][0].TypeOfClass()
== ParentClass.ChildClasses.FirstChildClass )
{
TestDictionary.ADictionary["FirstObject"][0]
= (FirstChildClass)TestDictionary.ADictionary["FirstObject"][0];
}
Console.ReadKey();
}
}
public abstract class ParentClass
{
public string Name { get; set; }
public string RandomValue { get; set; }
public ParentClass(string Name)
{
this.Name = Name;
}
public virtual void ReturnMessage()
{
Console.WriteLine($"This is the {this.GetType().Name} instance");
}
public virtual ChildClasses TypeOfClass()
{
return ChildClasses.NoChildClass;
}
public enum ChildClasses
{
NoChildClass = 0,
FirstChildClass = 1,
SecondChildClass = 2
}
}
public class FirstChildClass : ParentClass
{
public FirstChildClass(string Name)
: base(Name)
{
}
public override ChildClasses TypeOfClass()
{
return ChildClasses.FirstChildClass;
}
}
public class SecondChildClass : ParentClass
{
public SecondChildClass(string Name)
: base(Name)
{
}
public override ChildClasses TypeOfClass()
{
return ChildClasses.SecondChildClass;
}
}
class MultipleValueTypes
{
public readonly Dictionary<string, List<ParentClass>> ADictionary
= new Dictionary<string, List<ParentClass>>();
public void AddObject(string Name, ParentClass variable)
{
if ( !ADictionary.ContainsKey(Name) )
{
ADictionary.Add(Name, new List<ParentClass>());
}
ADictionary[Name].Add(variable);
}
}
If the intention is to cast the whole list from List<ParentClass> to List<FirstChildClass> and List<SecondChildClass>, then Linq is your friend, just use the Cast function:
List<FirstChildClass> firstChildClasses = TestDictionary.ADictionary["FirstObject"]
.Cast<FirstChildClass>().ToList();
List<SecondChildClass> secondChildClasses = TestDictionary.ADictionary["SecondObject"]
.Cast<SecondChildClass>().ToList();

Create game inventory system, without casting to derived

I am trying to implement a high-performance game inventory system. I have This abstract base class to store different type of items in Inventory, for example, Coin, Flashlight, Knife etc..
public abstract class ObtainableItem
{
public string Name { get; private set; }
public ObtainableItem(string name)
{
Name = name;
}
}
For example, I have a DoorKey which opens a door. DoorKey has a property KeyCode which will be used for opening a door.
public class DoorKey : ObtainableItem
{
public int KeyCode { get; private set; }
public DoorKey() : base("key")
{
KeyCode = 1234;
}
}
All ObtainableItem are stored in Inventory
public class Inventory
{
const int slotCount = 2;
ObtainableItem[] slots = new ObtainableItem[slotCount];
public Inventory()
{
slots[0] = new DoorKey();
}
}
Now imagine user drags DoorKey from his Inventory on a Door and triggers Open method
public class Door
{
public void Open(ObtainableItem key)
{
if (key is DoorKey)
{
DoorKey doorKey = (DoorKey)key;
if (doorKey.KeyCode == 1234)
{
// Open door
}
}
else
{
// "can't use this item on a door"
}
}
}
How to avoid cast from ObtainableItem to a DoorKey? I have read that using casting is bad practice and it points at a bad code oop design. Ideally, a Door class should look like this. Is there any pattern I should for my inventory system?
public class Door
{
public void Open(DoorKey key)
{
if (key.KeyCode == 1234)
{
// Open door
}
}
}
There are always exceptions that can be made for ease of implementation and readability. What you describe is common, if not typical.
An alternative would be to have the "control" logic in the class that calls Door.Open. This could be easily achieved with a touch of reflection:
public abstract class ObtainableItem
{
public string Name { get; private set; }
public ObtainableItem(string name)
{
Name = name;
}
}
public abstract class WorldItem
{
}
public interface IActsOn<in TWorldItem>
where TWorldItem : WorldItem
{
void ApplyTo(TWorldItem worldItem);
}
public class World
{
// If profiling shows that this is a performance issue, a cache keyed by tWorldItem, tInvItem
// should fix it. No expiry or invalidation should be needed.
private Action<ObtainableItem, WorldItem> GetApplyTo(Type tWorldItem, Type tInvItem)
{
var tActOn = typeof(IActsOn<>).MakeGenericType(tWorldItem);
if (!tActOn.IsAssignableFrom(tInvItem))
{
return null;
}
var methodInfo = tActOn.GetMethod(nameof(IActsOn<WorldItem>.ApplyTo));
return new Action<ObtainableItem, WorldItem>((invItem, worldItem) =>
{
methodInfo.Invoke(invItem, new object[] { worldItem });
});
}
public bool IsDropTarget(WorldItem worldItem, ObtainableItem item)
=> GetApplyTo(worldItem.GetType(), item.GetType()) != null;
public void ActOn(WorldItem worldItem, ObtainableItem item)
{
var actOn = GetApplyTo(worldItem.GetType(), item.GetType());
if (actOn == null)
{
throw new InvalidOperationException();
}
actOn(item, worldItem);
}
}
While this slightly complicates the implementation of World, it simplifies the implementation of various objects:
class Door : WorldItem
{
public void Unlock(string bitting)
{
if (bitting == "1234")
{
Console.WriteLine("Door Opened");
}
else
{
Console.WriteLine("Door could not unlock");
}
}
}
class DoorKey : ObtainableItem, IActsOn<Door>
{
private readonly string Bitting;
public DoorKey(string bitting)
: base("Key")
{
this.Bitting = bitting;
}
public void ApplyTo(Door worldItem)
{
worldItem.Unlock(this.Bitting);
}
}
class RubberChicken : ObtainableItem
{
public RubberChicken()
: base("Rubber chicken")
{
}
}
Example usage:
class Program
{
static void Main(string[] args)
{
var key1 = new DoorKey("1234");
var key2 = new DoorKey("4321");
var rubberChicken = new RubberChicken();
var door = new Door();
var world = new World();
Debug.Assert(!world.IsDropTarget(door, rubberChicken));
Debug.Assert(world.IsDropTarget(door, key1));
world.ActOn(door, key2);
world.ActOn(door, key1);
Console.ReadLine();
}
}

Inheritance with packages/namespaces [C#]

I want to redefine the classes of a package in a sub-package while keeping the hierarchy.
I would have wanted to do something like this :
namespace RPG {
public class Actor {}
public class Character : Actor {}
}
public class Actor : RPG.Actor {}
//kind of a diamond problem
public class Character : Actor, RPG.Character {}
I know this is incorrect ; C# doesn't support multiple inheritance, but I don't know the best way to resolve this kind of redefinition.
Interfaces doesn't solve my problem. I could do something like that using composition :
public class Character : Actor {
private RPG.Character basis;
// and do this for each attribute and method
public int atk { get { return basis.atk } set { basis.atk = value; } }
}
but it doesn't look good. Moreover, I ran into another problem with this way
namespace RPG {
public class Actor {
public List<Stat> stats { get; set; }
}
public class Stat {}
}
public class Actor {
private RPG.Actor basis;
//I can't do that because Stat does not inherit from RPG.Stat
public override List<RPG.Stat> stats { get; set; }
}
public class Stat {
private RPG.Stat basis;
}
What is the best way to resolve my problem ?
Use composition instead of inheritance.
It's tough to draw a direct example because you didn't provide any actions for your RPG actor/characters but the concept is that you inject the behaviors in the constructor of your class.
In this case "move" is the behavior:
class Fighter
{
public int Health = 100;
public string Name;
private Move _move;
public string MoveName
{
get
{
return _move.Name;
}
}
public int MoveDamage
{
get
{
return _move.Damage;
}
}
public Fighter(string name, Move defaultMove)
{
Name = name;
_move = defaultMove;
}
public void Attack(Fighter defendant)
{
if (_move != null)
_move.Attack(defendant);
}
public void SetMove(Move move)
{
if (move != null)
_move = move;
}
}
abstract class Move
{
public int Damage { get; set; }
public string Name { get; set; }
protected Move(int damage,string name)
{
Damage = damage;
Name = name;
}
public void Attack(Fighter defendant)
{
defendant.Health -= Damage;
}
}
class PunchMove:Move
{
public PunchMove() : base(5, "Punch")
{
}
}
class KickMove:Move
{
public KickMove() : base(7, "Kick")
{
}
}
try this.
namespace RPG {
public class Actor {
public void d(){
System.Console.Write("fhdf");
}
}
public class Character : Actor {}
}
////////////////
public class Character : RPG.Character {}
class Program
{
static void Main()
{
Character c = new Character();
c.d();
Console.WriteLine("Hello, World!");
}
}

Interfaces and inheritance with derived class

I am stuck on interfaces and inheritance. If I implement two classes who both have an interface each, how would I be able to add the properties of Class A and B together? For instance I wanted to associate firstitem with the seconditem.
public interface IAlpha
{
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Xml, ResponseFormat = WebMessageFormat.Xml, UriTemplate = "/AddBravoToAlpha/{firstitem}/{seconditem}")]
void AddBravoToAlpha(int firstitem, int seconditem);
}
public interface IBravo
{
// what goes in here?
}
public Class Alpha
{
public Alpha()
{
AlphaAdd = new List<Bravo>();
}
int Firstitem { get; set }
public List<Bravo> AlphaAdd { get; set; }
}
public Class Bravo
{
public Bravo()
{
BravoAdd = new List<Alpha>(); //not sure if Bravo can access Alpha (derived class)
}
int Seconditem { get; set }
Guid Indexer { get; set }
public List<Alpha> BravoAdd { get; set; }
}
public Class BravoDoesAlpha : IBravo, IAlpha //????
{
List<Alpha> alpha = new List<Alpha>();
List<Bravo> bravo = new List<Bravo>();
public void AddBravoToAlpha(int firstitem, int seconditem)
{
var result = alpha.Where(n => String.Equals(n.Firstitem, firstitem)).FirstOrDefault();
var result1 = bravo.Where(n => String.Equals(n.Seconditem, seconditem)).FirstOrDefault();
if (result != null)
{
result.BravoAdd.Add(new Alpha() { Firstitem = firstitem });
}
if (result1 != null)
{
result1.AlphaAdd.Add(new Bravo() { Seconditem = seconditem });
}
}
}
Okay, so the question you are being asked is basically one about how to do a certain kind of refactoring known as "extracting" an interface.
This is one of the more easy refactorings to do and to understand if you understand interfaces vs. types.
All interfaces are types, but not all types are interfaces.
Now let's assume we are dealing in a world with two families of types: classes and interfaces (as in your example).
Instead of working your example directly, I will work a different but clearer example that does not use Alpha, Bravo, Charlie, Epsilon, etc. because this kind of stuff makes it harder to see the meaning.
First, here's the before:
public class Dog
{
public void Bark() { Console.WriteLine("Woof!"); }
public int NumberOfDogLegs { get { return 2; } }
public int NumberOfDogFriends { get; set; } // this can be set
private string SecretsOfDog { get; set; } // this is private
}
public class DoorBell
{
public void Chime() { Console.WriteLine("Ding!"); }
}
To extract the interface of a class, simply, well, extract all the public members of the class to an interface.
public interface IDog
{
void Bark();
int NumberOfDogLegs { get; }
int NumberOfDogFriends { get; set; }
}
public interface IDoorBell
{
void Chime();
}
Now to really make use of OOP, you can find a way to abstract IDog and IDoorBell. What do they have in common? Well, the obvious one is they both make a noise. So we make a new interface, public interface IMakeANoise and say that IDog and IDoorBell both implement it.
public interface IMakeANoise
{
void MakeNoise();
}
public interface IDog : IMakeANoise
{
void Bark();
int NumberOfDogLegs { get; }
int NumberOfDogFriends { get; set; }
}
public interface IDoorBell : IMakeANoise
{
void Chime();
}
And now we have a new method to implement on Dog and DoorBell.
public class Dog : IDog
{
public void Bark() { Console.WriteLine("Woof!"); }
public int NumberOfDogLegs { get { return 2; } }
public int NumberOfDogFriends { get; set; } // this can be set
private string SecretsOfDog { get; set; } // this is private
public void IMakeANoise() { Bark(); }
}
public class DoorBell : IDoorBell
{
public void Chime() { Console.WriteLine("Ding!"); }
public void IMakeANoise() { Chime(); }
}
Now let's say we are actually writing a video game and Dog and DoorBell are both things that we can show on the screen. Well, this makes them a lot bigger because we will need to provide more information like their coordinates, their states, etc.
In this case, Dog and DoorBell may be very different to us but are similar enough to potentially merit sharing a base class. (Really, this is a stretch, but it does get the point across.)
Without adding all those new interfaces and their implementations, let's just do the "sharing a base class" refactoring for what we already have.
public class RenderableThing : IMakeANoise, IDoAThousandOtherThings
{
protected virtual string MyNoiseToMake { get { return ""; } }
public virtual void MakeANoise()
{
Console.WriteLine(MyNoiseToMake);
}
}
public class Dog : RenderableThing, IDog
{
protected override string MyNoiseToMake { get { return "Woof!"; } }
public void Bark() { MakeANoise(); } // see what we did there?
// Notice that I am not declaring the method MakeANoise because it is inherited and I am using it by overriding MyNoiseToMake
public int NumberOfDogLegs { get { return 2; } }
public int NumberOfDogFriends { get; set; } // this can be set
private string SecretsOfDog { get; set; } // this is private
}
public class DoorBell : RenderableThing, IDoorBell
{
public void Chime() { Console.WriteLine("Ding!"); }
public override void MakeANoise()
{
Chime(); Chime(); Chime(); //I'll do it my own way!
}
}
You may wonder, what's the point? So we can do this...
IMakeANoise dogNoiseMaker = new Dog();
IMakeANoise doorBellNoiseMaker = new DoorBell();
IList<IMakeANoise> listOfNoiseMakers = new List<IMakeANoise>();
listOfNoiseMakers.Add(dogNoiseMaker);
listOfNoiseMakers.Add(doorBellNoiseMaker);
foreach (IMakeANoise noiseMaker in listOfNoiseMakers)
{
noiseMaker.MakeANoise();
}
// This will output
// Woof!
// Ding!
// Ding!
// Ding!
I'm going to take a shot in the dark and venture a guess that you don't quite understand what interfaces and inheritance is. I'll start off by explaining what interfaces are:
Interfaces contain only the definitions of methods, properties, events or indexers that an inheriting class must implement.
For example:
interface IExample
{
void HelloWorld();
}
class ExampleClass : IExample
{
public void HelloWorld()
{
Console.WriteLine("Hello world.");
}
}
Now for Inheritance; when you derive a class from a base class the derived class will inherit all members of the base class except for the constructors. Note: Depending on the accessibility of the members in the base class it's children may or may not be able to access the parents members.
public class Animal
{
public string Name { get; set; }
public Animal(string name)
{
Name = name;
}
public void Talk()
{
Console.WriteLine("{0} is talking", Name);
}
}
public class Cat : Animal
{
public Cat(string name) : base(name) { }
}
public class Dog : Animal
{
public string FurColor { get; set; }
public Dog(string name, string furColor) : base(name)
{
FurColor = furColor;
}
public void Greeting()
{
Console.WriteLine("{0} has {1} fur.", Name, FurColor);
}
}
class Program
{
static void Main(string[] args)
{
var cat = new Cat("Rex");
cat.Talk();
var dog = new Dog("Beanie", "Red");
dog.Talk();
}
}

Reducing constructor boiler plate code

I often end up writing classes like this:
public class Animal
{
public string Colour { get; set; }
public int Weight { get; set; }
public Animal(Dog data)
{
this.Colour = data.Colour;
this.Weight = data.Weight;
}
public Animal(Cat data)
{
this.Colour = data.Colour;
this.Weight = data.Weight;
}
}
When you have lots of properties and types then you quickly end up with a lot of boiler plate code. Ideally in this situation I would just create an IAnimal interface and reference that. I'm currently in a situation where the Dog and Cat classes exist in a third party assembly and I can't modify them. The only solution that I can come up with is:
public class Animal
{
public string Colour { get; set; }
public int Weight { get; set; }
public Animal(Cat data){Init(data);}
public Animal(Dog data){Init(data);}
private void Init(dynamic data)
{
this.Colour = data.Colour;
this.Weight = data.Weight;
}
}
This works but I lose all type safety, is there a better solution than constructor injection?
Thanks,
Joe
EDIT: Here is a real world example. I have a third party library which returns 3 objects called:
GetPageByIdResult
GetPagesByParentIdResult
GetPagesByDateResult
(These are all auto generated classes from a service reference and the properties are pretty much identical)
Instead of dealing with these three objects I want to deal with a single PageData object or a collection of them.
You can have the logic in one common constructor that all the other constructors call:
public class Animal
{
public string Colour { get; set; }
public int Weight { get; set; }
public Animal(Dog data) : this (data.Colour, data.Weight)
{
}
public Animal(Cat data) : this (data.Colour, data.Weight)
{
}
private Animal(string colour, int weight)
{
this.Colour = colour;
this.Weight = weight;
}
}
This is pretty similar to your second solution but it doesn't lose type safety.
I'm currently in a situation where the Dog and Cat classes exist in a
third party assembly and I can't modify them
I'd suggest Automapper-based solution:
public static class AnimalFactory
{
public static Animal Create<T>(T source)
where T : class
{
Mapper.CreateMap<T, Animal>();
return Mapper.Map<Animal>(source);
}
}
Usage:
var catAnimal = AnimalFactory.Create(cat);
var dogAnimal = AnimalFactory.Create(dog);
Of course, you can provide a way to custom mapping configuration, if needed.
If you do not want to have the class littered like that you can try Extension methods?
public static Animal ToAnimal(this Dog item)
{
return new Animal() {Weight = item.Weight, Colour = item.Colour};
}
public static Animal ToAnimal(this Cat item)
{
return new Animal() {Weight = item.Weight, Colour = item.Colour};
}
try using json serializer's, with that we can ensure type safety.
public class Animal
{
public string Colour { get; set; }
public long Weight { get; set; }
public string Name { get; set; }
public Animal Create<T>(T anyType)
{
return GetObject<T, Animal>(anyType);
}
public K GetObject<T, K>(T type1)
{
try
{
var serialized = JsonConvert.SerializeObject(type1);
return JsonConvert.DeserializeObject<K>(serialized);
}
catch (Exception ex)
{
return default(K);
}
}
}
class Program
{
public static void Main(string[] args)
{
Animal obj = new Animal();
var animal = obj.Create(new { Colour = "Red", Weight = 100 });
//here you can pass any object, only same name properties will be initialized..
Console.WriteLine(animal.Colour + " : " + animal.Weight);
Console.ReadKey();
}
}

Categories