public abstract class Person
{
protected string name;
public Person(string firstName)
{
name = firstName;
}
{
public BusinessPerson : Person
{
public BusinessPerson(string newName) : base(newName)
{
}
}
public class Group : CollectionBase
{
public void Add(Person newPerson)
{
List.Add(newPerson);
}
}
int Main
{
Group VariousPeople = new Group();
VariousPeople.Add(new BusinessPerson("Jack")); // says invalid arguments
}
================================================================================
If I am correct shouldn't polymorphism allow me to store derived types in a container of
base types? Why doesn't this work for me?
It works fine for me. Your code in the question is missing some braces and things, but once fixed, it compiles and works fine on my compiler. Fixed code is below.
internal class Program
{
private static void Main(string[] args)
{
Group VariousPeople = new Group();
VariousPeople.Add(new BusinessPerson("Jack"));
}
}
public abstract class Person
{
protected string name;
public Person(string firstName)
{
name = firstName;
}
}
public class BusinessPerson : Person
{
public BusinessPerson(string newName)
: base(newName)
{
}
}
public class Group : CollectionBase
{
public void Add(Person newPerson)
{
List.Add(newPerson);
}
}
Related
I have 3 classes that have instance functions that are completely identical. Is there any way to reuse these instance methods or should I have a copy in all 3 classes e.g.
public class myclass1
{
public string METHOD;
public string RATE;
public string QTY;
void parseFunctionA()
{
}
void parseFunctionB()
{
}
void parseFunctionC()
{
}
}
public class MYCLASS2
{
public string PRICE;
public string WEIGHT;
void parseFunctionA()
{
}
void parseFunctionB()
{
}
void parseFunctionC()
{
}
}
For me two most popular ways would be to do it using:
Inheritance:
public class Program
{
public static void Main(string[] args)
{
var one = new myclass1();
var two = new myclass2();
one.parseFunctionA();
two.parseFunctionC()
}
// Common class can be abstract if you do want to
// prevent it to be instantiated by itself (prevents var common = new Common())
public class Common
{
// Methods made public only for example usage in Main
public void parseFunctionA()
{
}
public void parseFunctionB()
{
}
public void parseFunctionC()
{
}
}
public class myclass1 : Common
{
public string METHOD;
public string RATE;
public string QTY;
}
public class myclass2 : Common
{
public string PRICE;
public string WEIGHT;
}
}
Or composition:
public class Program
{
public static void Main(string[] args)
{
var common = new Common();
var one = new myclass1(common);
var two = new myclass2(common);
}
public class Common
{
public void parseFunctionA()
{
}
public void parseFunctionB()
{
}
public void parseFunctionC()
{
}
}
public class myclass1
{
private Common _common;
public myclass1(Common common)
{
_common = common;
}
public string METHOD;
public string RATE;
public string QTY;
// use _common as you see fit, in methods, in properties, etc.
}
public class myclass2
{
private Common _common;
public myclass2(Common common)
{
_common = common;
}
public string PRICE;
public string WEIGHT;
// use _common as you see fit, in methods, in properties, etc.
}
}
There are also other methods mentioned in comments under your original post.
Mind that there are no safety features in this example.
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();
I have the following base class:
public class Base
{
public string LogicalName { get; set; }
public int NumberOfChars { get; set; }
public Base()
{
}
public Base(string logicalName, int numberOfChars)
{
LogicalName = logicalName;
NumberOfChars = numberOfChars;
}
}
and the following derived classes:
public class Derived1 : Base
{
public const string EntityLogicalName = "Name1";
public const int EntityNumberOfChars = 30;
public Derived1() : base(EntityLogicalName, EntityNumberOfChars)
{
}
}
public class Derived2 : Base
{
public const string EntityLogicalName = "Name2";
public const int EntityNumberOfChars = 50;
public Derived2()
: base(EntityLogicalName, EntityNumberOfChars)
{
}
}
and I also have this function that is provided by a service:
public IEnumerable<T> GetEntities<T>(string entityName, int numberOfChars) where T : Base
{
//Some code to get the entities
}
My problem is how can I call this function generically? I want to call it with something that looks like this:
public void TestEntities<T>() where T : Base
{
var entities = GetEntities<T>(T.EntityLogicalName, T.EntityNumberOfChars);
//some other code to test the entities
}
This of course doesn't work because at this point T is not known. How can I accomplish something similar to this? EntityLogicalName and EntityNumberOfChars are characteristics that all Base derived classes have and they never change for each derived class. Can I get them from the Base class without instantiating objects or some other way that I am not seeing?
Replace constants with getter abstract properties
public abstract class Base
{
public abstract string LogicalName { get; }
public abstract int NumberOfChars { get; }
public Base()
{
}
}
public class Derived1 : Base
{
public string LogicalName { get { return "Name1"; } }
public int NumberOfChars { get { return 30; } }
public Derived1() : base()
{
}
}
Also, you will be able to put some logic into overriden getter, e.g. :
...
public string LogicalName { get { return this.EntityMap.Name; } }
...
UPDATE: The fact that you do not want to instantiate object from class but want to be able to get that string in a strongly typed manner can be handled in one more way. It is totally separate from answer above ( Since you can't override static props in c#). Consider the following code. We are adding one more class here, but LocatorInner can be a member of BaseClass. We are using this approach a lot in several existing apps.:
public class Locator
{
public static class LocatorInner<T> where T : BaseClass
{
public static string Name { get; set; }
}
public static string GetName<T>() where T : BaseClass
{
return LocatorInner<T>.Name;
}
public static void SetName<T>(string name) where T : BaseClass
{
LocatorInner<T>.Name = name;
}
}
public class BaseClass
{
}
public class DerivedClass: BaseClass
{
static DerivedClass()
{
Locator.LocatorInner<DerivedClass>.Name = "me";
}
}
public class TestClass<T> where T : BaseClass
{
public void Method()
{
var name = Locator.GetName<T>();
}
}
IMHO, I believe using constants here is a bad design decision.
You can either solve the issue using #vittore approach, but for me it sounds like you should use meta-programming with attributes if you're looking to get data from the T generic argument
For example, what about:
public class LogicalNameAttribute : Attribute
{
public LogicalNameAttribute(string name)
{
Name = name;
}
public string Name { get; private set; }
}
public class NumberOfCharsAttribute : Attribute
{
public NumberOfCharsAttribute (int number)
{
Number = number;
}
public string Number { get; private set; }
}
[LogicalName("Name1"), NumberOfChars(30)]
public class Derived1 : Base
{
public Derived1() : base()
{
}
}
Now your service method can extract attribute metadata as follows:
public void TestEntities<T>() where T : Base
{
LogicalNameAttribute logicalNameAttr = typeof(T).GetCustomAttribute<LogicalNameAttribute>();
NumberOfCharsAttribute numberOfCharsAttr = typeof(T).GetCustomAttribute<NumberOfCharsAttribute >();
Contract.Assert(logicalNameAttr != null);
Contract.Assert(numberOfCharsAttr != null);
string logicalName = logicalNameAttr.Name;
int numberOfChars = numberOfCharsAttr.Number;
// Other stuff
}
There's a performance penalty because you need to use reflection to get attributes applied to T, but you gain the flexibility of not forcing derived classes to provide this static info.
As #vittore mentioned, move the properties to base,pass the hard coded values from derived and in creation use just defautl(T)
public IEnumerable<T> GetEntities<T>(string entityName, int numberOfChars) where T : Base
{
yield return default(T); //Is its always class use new constraint and return new T();
}
I've recently made a switch from Java to C# and I'm wondering why I'm unable to set the property of a derived class as shown in the example below:
public abstract class Vehicle
{
private string name;
public void setName(string name)
{
this.name = name;
}
}
public class Car : Vehicle
{
setName("Car")
}
Your method can't be called directly in the class body, it has to be called from another method (the constructor for instance).
Try this:
public abstract class Vehicle
{
private string name;
public string getName()
{
return name;
}
public string setName(string name)
{
this.name = name;
}
}
public class Car : Vehicle
{
public Car()
{
setName("Car");
}
}
You need either an assignment call or another method to call setName. How is the compiler supposed to know when to execute this method call? Do this:
public class Car : Vehicle
{
public string SetCarName()
{
base.setName();
}
}
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.