I feel like I skipped a C# class or two, but here's my dilemma:
I have an abstract class from which I derive multiple child classes.
I know for sure that for each of the child classes I will have a constructor that needs a certain static object as a model and this object will be different for each of the child classes.
My first approach was to make a public static object in the abstract parent class and then, before I start creating any instances of the child classes, I would modify it for each of them, but it turns out that this way I actually make only ONE static object, for the abstract class, and each of it's child classes uses it.
How could I solve the problem?
To be more exact, here is the pseudocode:
The parent abstract class:
abstract class AbstractClass
{
static public ModelObject Model;
...
}
One of the child classes:
class Child : AbstractClass
{
...
public Child()
{
this.someField = Model.someField;
}
}
EDIT:
The Model needs to be a member of the "ModelObject" class, it should NOT be a singleton or anything else.
EDIT2:
To be even more exact, i chose this implementation for a game of chess: I have an abstract class for the chess pieces and the child classes represent the concrete pieces of the game: pawns, knights, et cetera.
The abstract class inherits from MeshMatObject, a class that represents generic 3d objects with the basic functionality, like rotations, meshes, materials, textures and so on and it defines abstract methods for chess game pieces, like GetPossibleMoves().
The Model object I was talking about above is a member of the MeshMatObject and, in my opinion, should be defined outside the class just once and then used for all the pieces. I mean: for example all the pawns have the same mesh and texture, so I don't see the point of giving a model as a parameter every time you want to make a pawn.
You can get around the shared static field by making your Abstract class generic. Each generic class will get it's own copy of the static fields.
abstract class AbstractClass<T>
{
static public ModelObject Model;
...
}
Then each child class will use a different instance of the static field.
class Child : AbstractClass<Child>
{
...
public Child()
{
this.someField = Model.someField;
}
}
It doesn't matter that AbstractClass doesn't reference the generic parameter. You are only using it to give each child class a unique instance of the base class.
I tend to use something similar to #shf301's solution. Depending on your needs it may useful to setup the base class as:
abstract class AbstractClass
{
}
abstract class AbstractClass<TModel> : AbstractClass
where TModel : ModelObject
{
static public TModel Model;
...
}
This allows me a common base class that I can work with in non-generic functions. This also allows derived types to choose the exact model type and can cut down on casting.
How about a factory to decouple your classes from an inherited Model:
public static class ModelObjectFactory
{
public static ModelObject GetModel<T>(T obj)
{
// return ModelObject according to type of parameter
}
}
class Child
{
public Child()
{
ModelObject mo = ModelObjectFactory(this);
this.someField = mo.someField;
}
}
Related
The question I asked here brought me thus far on my project:
abstract class Base<T> where T:ContentBase
{
//base functionality
}
class Foo : Base<FooContent>
{
//overrides
}
class Bar : Base<BarContent>
{
//overrides
}
Is there a way to make an array or List that can hold both Foo and Bar objects or would I have to look at making a record or something?
Thanks in advance.
You could add a non-generic abstract class Base that Base<T> inherits from, and then make a List<Base>. So extending your code might look something like this:
abstract class Base
{
//base functionality (non-generic)
}
abstract class Base<T> : Base where T : ContentBase
{
//base functionality acting on T
}
class Foo : Base<FooContent>
{
//overrides
}
class Bar : Base<BarContent>
{
//overrides
}
I'm assuming from the example code that FooContent and BarContent derive from ContentBase. I'm also assuming that the code follows the SOLID principles and especially LSP.
A generic collection could be defined in terms of ContentBase.
var collection = new List<ContentBase>();
The collection can hold instances of FooContent, BarContent, and ContentBase.
But apparently that is a need to hold the ContentBase and derived types within another type. (It is not clear from the question why this is needed.)
public class ContentAdaptor
{
public ContentAdaptor(ContentBase content)
{
_content = content;
}
...
private ContentBase _content;
}
The ContentAdaptor type holds a reference to an instance of ContentBase. The instance could be of a derived type.
A collection of ContentAdaptor:
var collection = new List<ContentAdaptor>();
I have a suspicion that FooContent and BarContent may violate LSP and are not substitutable for each other. Is that the case? If you have types that are fundamentally different but you want to process the objects in a polymorphic way, consider an interface.
public interface IProcess
{
bool Process();
}
Here ContentBase implements the IProcess interface. But note that a SomeOtherContent type that doesn't derive from ContentBase can also implement the IProcess interface.
public class ContentBase : IProcess
{
// Implement the IProcess interface.
}
A collection of IProcess:
var collection = new List<IProcess>();
The Process method can be called on each object in the collection. Each type provides its own implementation of the Process method.
I am struggling to formulate my question properly, I hope I can clarify it through the following description:
I have an abstract generic base class that is supposed to describe a specific container item, upon other things, and another abstract class of the same name to reference the generic classes by. I also created an interface to reference them by, both work but still result in the same issue eventually. For this example i am using the shared base class
public abstract class ItemEditorState
{
}
and the derived generic class
public abstract class ItemEditorState<T> : ItemEditorState where T : Item
{
public abstract SimpleDatabase<T> Items { get; set; }
public abstract void DoStuff();
...
}
So far so good.
Now I have classes deriving from ItemEditorState<T> corresponding to different Items.
public class EditorStateItemA : ItemEditorState<ItemA>
{
private ItemADatabase _itemADatabase; //ItemADatabase is public class ItemADatabase : SimpleDatabase<ItemA> {}
public override SimpleDatabase<ItemA> Items { get => _itemADatabase; set => _itemADatabase = value; }
public override void DoStuff(){}
...
}
So far so good again.
Now I have a static manager class holding a List<ItemEditorState> of references to all ItemEditorStates, such as EditorStateItemA, EditorStateItemB etc.
public static class ItemEditorStateManager
{
public static List<ItemEditorState> itemEditorStates = new List<ItemEditorState>();
public int GetState(int index) => itemEditorStates[index];
}
But since I reference the derived class instances by the shared abstract base class (or in another case the IItemEditorState interface), I can't access any members.
What I would like to do is access the Items list of any of EditorStateItemA or EditorStateItemB within the list in the ItemEditorStateManagerfrom the ItemEditorStateManager.GetState(index) method.
I know I would probably have to cast it to the proper class first, but I don't know the specific type at that point. I am sure my architecture is off, but I can't wrap my head around it.
I am having a C# abstract class which have some methods to be implemented by its children.
Though it is so, the initialization values for those children consist of two parts: one which is the same as the parent, and another one which is unique to the children.
public abstract class parentClass {
public abstract bool IsInputValid(string input); //children must implement this
public parentClass () {
//Some shared initialization
}
}
If the class is not abstract we could do something like this to implement that
public class parentClass {
public parentClass (string input) {
//Some shared initialization
}
}
public class childClass : parentClass {
public childClass (string input) : base (input) {
//Some unique initialization
}
}
But that cannot be done using abstract class and some more, the method not need not to be implemented (since it is not abstract).
So I am in a dilemma here. On one hand, I want to have some base initialization called and on the other, I also want to have some methods enforced.
So my question is, how do we normally implement such case? On one hand it is enforcing some base initialization, and on another some methods.
Note: I am new to abstract class so I would be glad to receive any inputs regarding it.
Where do I declare wrongly (if any)? If we cannot do so, is there a way to get around to produce the same result (that is, to enforce the child class to use certain signature for constructor)?
There should be no need to enforce this. You say that the base class has some common initialization and the child classes have their own specialized initialization as well.
This is enforced already, if you have this:
public abstract class Base
{
protected Base(int value) { ... }
}
Then you have a couple of guarantees:
Nobody can construct an object of the type Base since it is abstract
Nobody can construct an object that inherits from Base without indirectly calling the only existing constructor of Base, that takes an int value parameter.
The last part there is important.
A child class can deal with this type of base constructor in at least three ways:
It can provide a constructor that looks identical save the name of it, just passing the value down to the base constructor:
public class Child : Base
{
public Child(int value) : base(value) { ... }
}
It can provide a constructor that has this parameter but has additional parameters to the child class constructor as well:
public class Child : Base
{
public Child(int value, string other) : base(value) { ... }
}
It can provide a constructor that doesn't have the parameter to the base class, but manages to compute this parameter:
public class Child : Base
{
public Child(string other) : base(other.Length) { ... }
}
The last part also handles the case where the child constructor has no parameters at all:
public class Child : Base
{
public Child() : base(new Random().Next(100)) { ... }
}
Regardless of which approach you use, it is impossible to call the base class constructor without passing a value for that parameter, hence you have enforce the following:
Child classes has to be aware of the base class constructor and its parameter
But you cannot, and should not, try to enforce the presence of a particular constructor with a specific signature.
Now, having said that, what if you want to create some sort of common way to construct two distinct child classes, that has such different constructors, in such a way that code that uses them doesn't need to know the specifics of either constructor?
Enter the factory pattern (Wikipedia):
In class-based programming, the factory method pattern is a creational pattern that uses factory methods to deal with the problem of creating objects without having to specify the exact class of the object that will be created. This is done by creating objects by calling a factory method—either specified in an interface and implemented by child classes, or implemented in a base class and optionally overridden by derived classes—rather than by calling a constructor.
(quoted text copied from entry paragraph in the Wikipedia-article)
Here's a way to abstract away the presence and knowledge of such different constructors and child classes:
void Main()
{
Test(new Child1Factory());
Test(new Child2Factory());
}
public void Test(IBaseFactory baseFactory)
{
Console.WriteLine("In Test(...");
var b = baseFactory.Create();
}
public class Base
{
public Base(int value)
{
Console.WriteLine($"Base.ctor({value})");
}
}
public interface IBaseFactory
{
Base Create();
}
public class Child1 : Base
{
public Child1(int value) : base(value)
{
Console.WriteLine($"Child1.ctor({value})");
}
}
public class Child1Factory : IBaseFactory
{
public Base Create() => new Child1(42);
}
public class Child2 : Base
{
public Child2(string name) : base(name.Length)
{
Console.WriteLine($"Child2.ctor({name})");
}
}
public class Child2Factory : IBaseFactory
{
public Base Create() => new Child2("Meaning of life");
}
Pay special attention to the Test(...) method, as this has no knowledge of which Base child it will get, nor how to construct such an object. If you later on add new child types from Base, you will have to provide new factories as well but existing code that uses these factories should not need to be changed.
If you want a simpler factory pattern all you have to do is replace the interface and factory classes with a delegate:
void Main()
{
Test(() => new Child1(42));
Test(() => new Child2("Meaning of life"));
}
public void Test(Func<Base> baseFactory)
{
Console.WriteLine("In Test(...");
var b = baseFactory();
}
Final note here. Since the factory pattern means you will have to create a different type that does the actual construction of the object you can enforce the signature of that other type, either by
Adding parameters to the Create method on the factory interface
Specifying a delegate that has parameters to the factory delegate
This means you can enforce the signature of "the creation process". Still, you cannot enforce the presence or signature of a particular constructor, but the constructor is just a means to an end, create an object, and with the factory pattern you can actually formalize this pattern in your code and thus you should get what you want.
You cannot enforce the signature or even existence of constructors of your derived classes. (or any class for that matter)
I'm afraid that's the end of the story. You aren't doing anything wrong, it's just not possible.
Since you can't override constructors in c#, you cannot enforce the existence of a certain constructor in the derived class .
This means:
a constructor cannot be abstract, virtual etc
constructors aren't polymorphically
You cannot have an abstract constructor, but neither is there any need to.
All you need to do is remove the "abstract" keyword from your parentClass and you should be good to go.
I'm a bit confused at some code I recently came across. Here is a snippet. First of the Abstract Class Definition and then of the Class that inherits from it:
public abstract class BaseClass
{
protected static void MapEntityToModel(string paramOne, List<TypeDef> types)
{
// Some Logic Here
}
protected static void MapModelToEntity(ModelType model, ResultType result)
{
// Some Logic Here
}
}
public class BaseExtension : BaseClass
{
public static ViewModel MapModelToViewModel(Model m)
{
var result = new ViewModel();
// Some Logic Here
return result;
}
public static List<ViewModel> MapModelsToViewModels(List<TModel> models)
{
return models.Select(m => MapModelToViewModel(m)).ToList();
}
public static Model MapViewModelToModel(ViewModel v)
{
var result = new Model();
// Some Logic Here
return result;
}
}
So my understanding and usage of an Abstract Class has always been that any abstract methods within an Abstract Class must be overridden in the inherited Classes. If a method within an Abstract Class is not declared abstract, the derived Class can create an instance of itself within a method and directly call the non-abstract method of the Abstract Class.
But in either case the methods of the Abstract Class are used in the Derived Class. However, given the previous code snippets the Derived Class has no directly mapped signature or usage.
What then is the purpose of the Abstract Class in this particular scenario and why does it compile without error? I obviously am missing some concept of the Abstract Class and its appropriate implementation.
So my understanding and usage of an Abstract Class has always been that any abstract methods within an Abstract Class must be overridden in the inherited Classes
That is true, but the methods are not abstract, they are concrete (and static). Only virtual or abstract instance methods can be overridden.
What then is the purpose of the Abstract Class in this particular scenario and why does it compile without error?
Since the class has no abstract methods or properties I do not see why it is abstract, other than the author doesn't instances created for some reason.
static methods are not part of instances of the class
when you are saying a class is abstract you are saying that you cannot create instances of it.
Abstract on those classes serves no purpose apart from highlighting that creating instances of them is pointless as all methods are static anyway.
Also inheriting from them seems a little pointless as nothing is inherited - all the members are static.
You may as well have only the inherited class and make the base class an empty interface and move the static methods in it into the inherited class (an interface is in effect an abstract class with no method implementations - but you would normally have what are in effect abstract method definitions though)
abstract class a
{
public abstract string look();
public static string lookStatic()
{
return "look";
}
}
class b : a
{
public override string look()
{
return "look member";
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine(b.lookStatic());
var test = new b();
Console.WriteLine(test.look());
var c = (a) test;
Console.WriteLine(c.look());
Console.ReadLine();
}
}
I currently have a small object hierarchy that looks like this:
public class BaseClass {
// this class is empty and exists only so the others can extend it and share the
// same base type
}
public class ChildA : BaseClass {
public Subject<AssociatedClassA> Results;
}
public class ChildB : BaseClass {
public Subject<AssociatedClassB> Results;
}
In my design I would like to enforce that every class that extends from BaseClass should contain a Subject<SomeType> called Results. I'm wondering if there is a way that I can move Results into the base class or an interface such that I can supply the generic type for the Subject when constructing the base class. For example, it would be awesome if I could do something like this:
ChildA<AssociatedClassA> instance = new ChildA<AssociatedClassA>();
Or even better since there should really only be one template parameter that matches with ChildA if when I constructed it that could be taken care of for me:
ChildA instance = new ChildA();
// Results is automatically set to Subject<AssociatedClassA>
I'm stuck trying to implement this now as if I try to move Results into the base class the Subject requires a template parameter which I can't necessarily supply. There could potentially be more than 2 derived classes and I don't like the idea that someone extending this system has to know to add Results manually to each child class.
Following the suggestions of the 2 answers below this solves my desire to move Results into the base class, however I've run into another issue in that I was hoping to be able to use BaseClass as a generic parameter to methods such that any of the derived classes could be used. For example:
public void ProcessBaseClass(BaseClass base) {
// base could be ChildA or ChildB here
}
This no longer works since BaseClass now requires a type argument. Is there any way that I can have the best of both worlds here or am I stuck due to my design choices?
If appropriate, you can make the parent generic:
public class BaseClass<T> {
public Subject<T> Results;
}
public class ChildA : BaseClass<AssociatedClassA> {
}
public class ChildB : BaseClass<AssociatedClassB> {
}
You can make the base class itself generic:
public class BaseClass<T> {
public T Results { get; protected set; }
}