What is the best way to solve this?
A static member is one for all subclasses and i want a different static member for subclasses but with the same name so I can use vehicle.canDo; this should give me different arrays depending what class the vechicle instance really is.
I can just remove the static from canDo array but all instances of the same subclass should always have the same values in the canDo array so there is no need to have canDo array in every instances, this will be big waste of memory because i will have too many instances of this class.
class Vehicle {
public static List<string> canDo;
static Vehicle() {
canDo = new List<string>();
canDo.Add("go");
}
}
class Plane : Vehicle {
static Plane() {
canDo.Add("fly");
}
}
class Ship : Vehicle {
static Ship() {
canDo.Add("sail");
}
}
class Main {
static void Main(string[] args) {
Vehicle plane = new Plane();
Vehicle ship = new Ship();
plane.canDo; // Contains (go, fly and sail) i want only (go and fly)
ship.canDo; // Contains (go, fly and sail) i want only (go and sail)
}
}
What is the best way to solve this?
Do not abuse static methods for things that are not static. Simple like that.
Static has no inheritance and is NOT something that CAN have inheritance scenarios in any way.
You are fighting a battle by abusing a feature - not worth fighting. Please learn proper object orientation.
Note that you could also hide the canDo of the base class using new:
class Vehicle
{
public static List<string> canDo = new List<string>() { "go" };
}
class Plane : Vehicle
{
public new static List<string> canDo = new List<string>(Vehicle.canDo);
static Plane()
{
canDo.Add("fly");
}
}
You do not need static variables and constructors for that, just add base constructors(which is done by default, : base() is optional):
class Vehicle {
public List<string> canDo;
Vehicle() {
canDo = new List<string>();
canDo.Add("go");
}
}
class Plane : Vehicle {
Plane() : base() {
canDo.Add("fly");
}
}
class Ship : Vehicle {
Ship() : base() {
canDo.Add("sail");
}
}
UPDATE: based on the comment of #Eben Roux -
public abstract class Vehicle {
protected static List<string> _canDo;
protected abstract List<string> getCanDo();
public List<string> canDo{
{ get {
var _cando = new List();
_cando.AddRange(Vehicle._canDo);
_cando.AddRange(this.getCanDo());
return _cando;
}
}
}
static Vehicle() {
_canDo = new List<string>();
_canDo.Add("go");
}
}
class Ship : Vehicle {
protected static List<string> childCanDo;
protected override getCanDo(){
return Ship.childCanDo;
}
static Ship() {
childCanDo.Add("sail");
}
}
You need an instance of the canDo list per type. So either you can pass in the collection via the constructor or you can have a static on the subtype level.
Edit (to elaborate):
Since your sub class instance all have the same 'abilities' and you don't want to populate a list for each you would need a shared list. You are using inheritance where you probably want composition:
public abstract class Vehicle
{
protected List<string> canDo;
protected Vehicle(List<string> canDo)
{
this.canDo = canDo;
}
}
public class Plane : Vehicle
{
public Plane(List<string> canDo) : base(canDo)
{
}
}
I wouldn't go with a List<string> either but rather encapsulate it in a class that makes business sense (although I understand that this is only an example). To populate the canDo list you could go with a factory or a factory method on a subtype.
There are just so many ways to do this you will need to find something that's comfortable.
Although I did present a static as an alternative (since you were asking about it) I definitely would not use a static for this myself.
Related
I have two similar classes A and B, which contain the following code:
//A or B depending on class
public class LogicA
{
public List<Members> MembersA { get; set; } = new List<Member>();
public void AddMember(Member member)
{
MembersA.Add(member);
}
public List<Member> GetResultA()
{
return MembersA;
}
}
I want to use the MembersA and MembersB lists in another class (say logicC).
I have seen similar questions and they mostly involve single inheritance. The process I thought to use was to create instance of lists from two different classes in the third class through multiple inheritance but in C#, only interface support multiple inheritance and I am using classes, hence my issue.
Is there any reason that you need to use inheritance only?
Generally, the way of using a member of Class is follow
class logicC
{
static void Main(string[] args)
{
LogicA logicA = new LogicA();
LogicB logicB = new LogicB();
List<Member> memberA = logicA.memberA;
List<Member> memberB = logicB.memberB;
}
}
Both Logica.GetResultA and presumably LogicB.GetResultB return List<Member>. So there is no problem
LogicC can be
class LogicC{
void NoodleOnList(List<Member> input){
....
}
}
then
LogicC lc;
lc.NoodelOnList(la.GetMembersA());
lc.NoodelOnList(lb.GetMembersb());
Well, you should re-consider your design choices and think about how to make your code less prone to change.
You can create a new class to aggregate Lists from A, B. And via Composition this new class might access Lists from other inner objects.
public class logicC {
public LogicA logicA;
public LogicB logicB;
public List<Member> GetResultC() => logicA.GetResultA().Concat(logicB.GetResultB());
}
you can use static modifier for your methods for example:
public static class LogicA
{
public static List<Members> MembersA { get; set; } = new List<Member>();
public static void AddMember(Member member)
{
MembersA.Add(member);
}
public static List<Member> GetResultA()
{
return MembersA;
}
}
and use this like that:
using YourProject;
public class LogicC
{
Members members = new();
List<Members> membersList = new();
LogicA.AddMember(member);
membersList = LogicA.GetResult();
}
Let's say I've such code
public class Holded
{
protected internal int holdedID = 0;
}
public class Inventory : Holded
{
public Inventory() { }
public void changeHoldedID()
{
this.holdedID = 100;
}
}
public class Equipment : Holded
{
public Equipment() { }
public void writeHoldedID()
{
Console.WriteLine("Holded ID is: {0}!", this.holdedID);
}
}
public class Cargo : Holded
{
public Cargo() { }
}
If I'd call changeHoldedID and then writeHoldedID, console will still output a string like "Holded ID is: 0!". Now what I want to achieve is to have same base class (Holded) in both of classes. So if I'd change holdedID from Inventory, Equipment's writeHoldedID function would output "Holded ID is: 100!". Thanks and regards!
#Edit: More detailed: I have a game. Each person is a character, that owns Equipment, Inventory and Cargo class. Each class contains about 20 slots for "items". Now the thing is, that if you try to move an item, for ex. from inventory, to equipment, and there's such index of item, then the item is "swapped" - goes holded, and now I may throw such holded item into Equipment, Inventory or Cargo. That's why I'm in need to share such class between Eq/Inv/Cargo.
With this inheritance structure, what you are asking is 99.9% impossible.
When you create an Inventory object, you are also creating a Holded object with its own holdedID member. When you create an Equipment object, you get a new Holded object as well, with no relation to the old one. Thus, changes to one objects member won't affect the other, and you want it this way.
*To be clear, you don't get a seperate Holded object when creating a derived class, but it can be helpful to think of it in the way I described it.
I don't know why you want to do what you are asking, but its a pretty good bet you need to rework your understanding of inheritance, objects, and polymorphsim.
Now, I said this was 99.9% impossible. You can mark the base class member static which shares it among all instances of Holded (and derived classes), making your code possible. However, there is almost no chance you actually want to do this. static should only be used when you understand object-oriented design and the consequences of using it.
Have you considered, instead of "is a" inheritance type relationship a "contains a" relationship?
You could do something along the following lines:
public interface IHolded
{
Bar Foo();
}
public class Holded: IHolded { ... }
And now you have two options in how you want to implent Equipment and Inventory:
Directly exposing holded throgh a readonly property:
public class Inventory
{
public Inventory(IHolded holded) { ... }
public IHolded Holded { get; }
}
Having them implement the IHolded interface and delegating
implementation to holded.
public Equipment
{
private readonly IHolded holded;
public Equipment(IHolded holded) { this.holded = holded; }
public Bar Foo() { return holded.Foo() };
}
This way you are injecting a Holded object when creating Equipment and Inventory instances ensuring a consistent state in both instances.
A Dictionary to store the person and their HoldedId might work
public class Holded
{
protected internal static Dictionary<string, int> _personHoldedIDs;
internal string _person;
public Holded(string person)
{
_person = person;
if (_personHoldedIDs == null)
_personHoldedIDs = new Dictionary<string, int>();
if (!_personHoldedIDs.ContainsKey(_person))
_personHoldedIDs.Add(_person, 0);
}
}
public class Inventory : Holded
{
public Inventory(string person) : base(person) { }
public void changeHoldedID()
{
_personHoldedIDs[_person] = 100;
}
}
public class Equipment : Holded
{
public Equipment(string person) : base(person) { }
public void writeHoldedID()
{
Console.WriteLine("Holded ID is: {0}!", _personHoldedIDs[_person]);
}
}
Apologies for the title, I really don't know what to call this problem. I have an abstract class which describes the interface of some data collection. I would like to retrieve an instance list of all classes that derives from this, without littering the base class or the code that uses it with references to the new type name. In effect, I want to be able to add new derived classes of the base and the rest of the code should work unaffected.
Maybe some code will help illustrate the problem:
public abstract class BaseData
{
public static List<BaseData> getCollection()
{
return collection;
}
static private List<BaseData> collection = new List<BaseData>();
// the actual part of the interface.
public abstract int[] getSomeData();
protected BaseData()
{
// when some derived class is statically created, they get added to the static list.
collection.Add(this);
}
}
And then I can use the interface like this:
// some actual code file:
class App
{
public App()
{
foreach(var dataimpl in BaseData.getCollection())
{
//.. do something here.
var data = dataimpl.getSomeData();
}
}
}
The idea is, that I can now add new cases to this data collection in another file, without altering the other two pieces of code, like so:
// hidden implementation classes
class SomeImplementation1 : BaseData
{
// register the class in the base class list
static private SomeImplementation1 register = new SomeImplementation1();
public override int[] getSomeData() { return null; }
private SomeImplementation1() { }
}
class SomeImplementation2 : BaseData
{
// register the class in the base class list
static private SomeImplementation2 register = new SomeImplementation2();
public override int[] getSomeData() { return null; }
private SomeImplementation2() { }
}
The use cases are many, tests, data and such. The problem, however, is, that the static register variable in the child classes isn't actually instantiated (and thus, the parent constructor is not run, which in turn means the class is not registered in the collection) before the child class is referenced - that is, the static initializers will not run before an instance is created.
This then requires me to reference the child classes somewhere in a list, which defeats the whole purpose of this system. My question is, is this a common pattern - is there an existing solution or a somehow similar implementation to this - or can this code be fixed somehow?
Thanks
Get rid of the "abstract class which describes the interface" and use an actual interface.
interface IHaveData
{
int[] getSomeData();
}
Now this frees you up to implement registrations however you want. Here's one simple way that fits with your initial code:
class BaseData
{
private static readonly List<IHaveData> collection = new List<IHaveData>();
public static IEnumerable<IHaveData> getCollection()
{
return collection;
}
public static void Register(IHaveData instance)
{
collection.Add(instance);
}
}
class SomeImplementation1 : IHaveData
{
private static readonly SomeImplementation1 registration = new SomeImplementation1();
private SomeImplementation1()
{
BaseData.Register(this);
}
public int[] getSomeData() { return null; }
}
class SomeImplementation2 : IHaveData
{
private static readonly SomeImplementation2 registration = new SomeImplementation2();
private SomeImplementation2()
{
BaseData.Register(this);
}
public int[] getSomeData() { return null; }
}
UPDATE
You will need a container of some kind and manually register your instances or use reflection to instantiate your instances and add them to the container.
class SomeImplementation1 : IHaveData
{
public int[] getSomeData() { return null; }
}
class SomeImplementation2 : IHaveData
{
public int[] getSomeData() { return null; }
}
Manual Registration (Safest, but you do have to edit the registrations for each new implementation)
class BaseData
{
private static readonly List<IHaveData> collection = new List<IHaveData>
{
new SomeImplementation1(),
new SomeImplementation2()
//as you add more implementations, you'll need to add them here
};
public static IEnumerable<IHaveData> getCollection()
{
return collection;
}
}
Automatic Registration (No more editing registrations, but any constructor changes and you get runtime errors and tricky to debug)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
class BaseData
{
private static List<IHaveData> collection;
public static IEnumerable<IHaveData> getCollection()
{
if (collection == null)
{
var types = Assembly.GetExecutingAssembly().GetTypes()
.Where(type =>
type.IsClass &&
!type.IsAbstract &&
type.GetInterfaces().Any(i => i == typeof(IHaveData)));
//All implementation must have the same constructor signature. In this case, a parameterless constructor.
collection = new List<IHaveData>(types.Select(x => (IHaveData)Activator.CreateInstance(x)));
}
return collection;
}
}
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.
In my app, I have deal with several different "parameters", which derive from IParameter interface, and also ParamBase abstract base class. I currently have two different parameter types, call them FooParameter and BarParameter, which both derive from ParamBase. Obviously, I can treat them both as IParameters when I need to deal with them generically, or detect their specific type when I need to handle their specific functionality.
My question lies in specific FooParameters. I currently have a few specific ones with their own classes which derive from FooParameter, we'll call them FP12, FP13, FP14, etc. These all have certain characteristics, which make me treat them differently in the UI. (Most have names associated with the individual bits, or ranges of bits). Note that these specific, derived FP's have no additional data associated with them, only properties (which refer to the same data in different ways) or methods.
Now, I'd like to keep all of these parameters in a Dictionary<String, IParameter> for easy generic access. The problem is, if I want to refer to a specific one with the special GUI functions, I can't write:
FP12 fp12 = (FP12)paramList["FP12"] because you can't downcast to a derived type (rightfully so). But in my case, I didn't add any data, so the cast would theoretically work.
What type of programming model should I be using instead? Thanks!
There's nothing really wrong with this approach, except for maybe storing the parameters in a dictionary. What is the purpose of doing that? Especially if you key them on their class name.
I would just use a List<IParameter> and have a control go through the collection and pick the right subclass out of there.
m_Parameters = new List<IParameter>();
//This control needs FP12
foreach(var param in Parameters) {
var fp12 = param as FP12;
if (fp12 != null) {
//do something with the param.
break;
}
}
After writing the above I think I finally understand what you are trying to do. If you want to perform an operation that is available on FP12 on any subclass of FooParameter then you need to take that operation out of FooParameter altogether. Since your parameter is data and that data is the same across different subclasses of FooParameter, it makes sense to only have one implementation of FooParameter ("data" class) and multiple "operation" classes.
//The one implementation of IParameter for all FooParameters
public class FooParameter : IParameter {
string Data1 {get;set;}
}
//base class for Foo Operation, only stores FooParameter
public class FooOperationBase {
protected readonly FooParameter m_Param;
public FooOperationBase (FooParameter param) {
m_Param = param;
}
}
//specific operations on FooParameter go in this class
public class FooOperation12 : FooOperationBase {
public FooOperation12(FooParameter param) : base(param) {}
public void DoSomeOperation() {
return m_Param.Data1 + " transformed";
}
}
If paramList["FP12"] is a FP12, that cast will work. Of course, if it's not it will throw a InvalidCastException. You could also use as, if you're not sure what type the object will be.
Whether this is an ideal design is a separate issue. Ideally, you want to prefer polymorphism, meaning the subclass of FooParameter knows to use its new special functions internally, and the outside code doesn't have to cast, or use as or is.
I'm not 100% sure where you're coming from with this question, but you could do something like this:
class Program
{
static void Main(string[] args)
{
var paramList = new List<IParameter>();
paramList.Add(new FooParameter());
paramList.Add(new BarParameter());
paramList.Add(new F1());
paramList.Add(new F2());
foreach (var p in paramList)
{
p.DoCommonOperation();
DoSpecificOperation(p);
}
Console.ReadKey();
}
private static void DoSpecificOperation(IParameter p)
{
if (p is F1)
{
(p as F1).F1Method();
}
else if (p is F2)
{
(p as F2).F2Method();
}
}
interface IParameter
{
void DoCommonOperation();
}
abstract class ParamBase : IParameter
{
public virtual void DoCommonOperation()
{
Console.WriteLine("ParamBase");
}
}
class FooParameter : ParamBase
{
public override void DoCommonOperation()
{
Console.WriteLine("FooParameter");
}
}
class BarParameter : ParamBase
{
public override void DoCommonOperation()
{
Console.WriteLine("BarParameter");
}
}
class F1 : FooParameter
{
public override void DoCommonOperation()
{
Console.WriteLine("F1");
}
public void F1Method()
{
Console.WriteLine("F1.F1Method");
}
}
class F2 : FooParameter
{
public override void DoCommonOperation()
{
Console.WriteLine("F2");
}
public void F2Method()
{
Console.WriteLine("F2.F2Method");
}
}
}
Essentially you have a method in the class that controls the list of IParameter objects that knows how to call the specific implementations, and uses is/as to do so.
Just for sanity's sake, why not use Dictionary<Type, IParameter>? With a little generics, you could do this:
public interface IParameter { }
public class FP12 : IParameter { public string fieldFP12 { get; set; } }
public class FP11 : IParameter { public string fieldFP11 { get; set; } }
public static class DictionaryHelper
{
public static T GetParameter<T>(this Dictionary<System.Type,
IParameter> target) where T : IParameter
{
return (T)target[typeof(T)];
}
}
Sample program and output:
class Program
{
static void Main()
{
Dictionary<Type, IParameter> parameters =
new Dictionary<Type, IParameter>();
parameters.Add(typeof(FP12), new FP12 { fieldFP12 = "This is FP12" });
parameters.Add(typeof(FP11), new FP11 { fieldFP11 = "This is FP11"});
// THIS IS WHERE YOU GET THE IPARAMETER YOU WANT - THE GENERICS WAY...
var fp12 = parameters.GetParameter<FP12>();
var fp11 = parameters.GetParameter<FP11>();
Console.WriteLine(fp12.fieldFP12);
Console.WriteLine(fp11.fieldFP11);
Console.ReadLine();
}
}
The resulting output:
This is FP12
This is FP11