Generic base class with multiple children - c#

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; }
}

Related

Get derived (generic) class members from base class (or shared interface) reference

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.

Polymorphism, using methods of child classes

I have an interface IRecordBuilder and an abstract class Query with a field protected IRecordBuilder recordBuilder and a method public abstract IList<IRecords> GetRecordsFromResults();.
In Query child classes constructors, I specify a recordBuilder concrete type depending on which child class I am in, for exemple :
recordBuilder = new RecordsPerMonthBuilder(); //RecordsPerMonthBuilder implements IRecordBuilder
I would like to use my recordBuilder field in the implementations of the abstract method above, but the properties in the implementations of IRecordBuilder remains unknown at compile time and i can't use them.
Besides transfering recordBuilder from mother class to each child classes and instantiate it there with the proper type, is there a way to make the polymorphism work here ?
Here are the explanations in code format :
public interface IRecordBuilder
{
IRecords BuildRecord();
}
public class RecordsPerMonthBuilder : IRecordBuilder
{
public IRecords BuildRecord()
{
if(Foo != null) return new FooRecord(Foo); // class FooRecord : IRecord
return null;
}
public string Foo {get; set;}
}
public abstract class Query
{
protected IRecordBuilder recordBuilder;
public abstract IList<IRecords> GetRecordsFromResults();
}
public sealed class ConcreteQuery: Query
{
public ConcreteQuery()
{
RecordBuilder = new RecordsPerMonthBuilder();
}
public override IList<IRecords> GetRecordsFromResults()
{
var recordsList = new List<IRecords>();
recordBuilder.foo = "foo"; // IRecordBuilder does not contain a definition for foo
recordsList.Add(RecordBuilder.BuildRecord());
return recordsList;
}
}
I see three possible solutions for this:
Option 1: In your child class, cast the builder to the concrete type (since the child class created it, it knows the concrete type). If you do that, you might want to make the recordBuilder field readonly and pass it to the base constructor to ensure at compile time that its type cannot be changed.
Option 2: In your child class, keep an additional "strongly typed" reference to the record builder. (In fact, why do you even need the "interface typed" reference at all?)
public sealed class ConcreteQuery: Query
{
private RecordsPerMonthBuilder myBuilder;
public ConcreteQuery()
{
myBuilder = new RecordsPerMonthBuilder();
RecordBuilder = myBuilder;
}
public override IList<IRecords> GetRecordsFromResults()
{
var recordsList = new List<IRecords>();
myBuilder.foo = "foo";
recordsList.Add(myBuilder.BuildRecord());
return recordsList;
}
}
Option 3: Make your base class generic:
public abstract class Query<TBuilder> where TBuilder : IRecordBuilder
{
protected TBuilder RecordBuilder;
public abstract IList<IRecords> GetRecordsFromResults();
}
public sealed class ConcreteQuery : Query<RecordsPerMonthBuilder>
{
...
}
One area of confusion is that your Query class depends explicitly on one implementation of IRecordBuilder, RecordsPerMonthBuilder. The interface IRecordBuilder doesn't have a Foo property, but Query depends on the Foo property. Query is hard-coded to only use RecordsPerMonthBuilder.
It's difficult to see the intent. One way to clear it up is to make sure that any interaction between Query and an implementation of IRecordBuilder is defined in IRecordBuilder. Query should depend on the interface and shouldn't call any properties or methods that aren't in that interface.
If only one implementation of IRecordBuilder requires a Foo, then that value shouldn't be coming from your Query class because Query doesn't know that IRecordBuilder needs a Foo. It shouldn't know what an implementation of IRecordBuilder needs, only what it does.
Here's a way to move it around. You'll see this pattern a lot.
public abstract class Query
{
protected IRecordBuilder RecordBuilder { get; private set; }
protected Query(IRecordBuilder recordBuilder)
{
RecordBuilder = recordBuilder;
}
public abstract IList<IRecords> GetRecordsFromResults();
}
Now it will never know what the implementation of IRecordBuilder is. That's good. It's now impossible for it to depend on anything that's not in the IRecordBuilder interface. Now Query depends on an abstraction, applying the Dependency Inversion principle.
What about RecordsPerMonthBuilder? It depends on a value, Foo. Will every implementation of IRecordBuilder need that? If so you could add it to the interface:
IRecords BuildRecord(string foo);
But if only one implementation needs that value then it shouldn't come from Query, because Query shouldn't know the difference between one IRecordBuilder and another. I can't answer that more specifically because I don't know what Foo is.
Another suggestion: If the inheritance between Query and ConcreteQuery gives you any grief, just don't use inheritance. Sometimes trying to use inheritance creates complications and doesn't give us any benefit in return.

base class collection defined by derived class

I'm not even close to as experienced in C# as I am in C++, but trying to get better.
In C#, does there exist a way to create a base class that contains a property which is a List and then in the derived class define what T is for that concrete type?
public class Base
{
public List<T> Data { get; set; }
}
public class Derived : Base
{
// Declare to the world you use Base.data<Elephant>
// Callers of my Data property get Elephants
}
I imagine not, since you can no longer act on the interface in the base class since you wouldn't know what type you are getting until you know what type the actual instance is, but maybe there is some magical thing in C# that is similar to this?
You can make the base class generic like this:
public class Base<T>
{
public List<T> Data { get; set; }
}
And then when you create the derived class, you can specify T like this:
public class Derived : Base<Elephant>
{
}
For the consumers of Derived, the type of the Data property is List<Elephant>.

Forcing partial base Initialization (and methods) in Inherited Class Constructor C# (like abstract does to methods) - work around to do 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.

C# Derive From Generic Base Class (T : U<T>)

I am trying to find a way to derive a class from a generic base class. Say:
sealed public class Final : Base<Something>
{
}
public class Base<T> : T
where T : Anything // <-- Generics do not allow this
{
}
In C# this does not seem to be possible.
Is there any other solution to achieve something similar to this?
I found this StackOverflow question, but it doesn't seem to solve the issue, or at least I do not understand how it should.
EDIT:
The result I'd like to get is to be able to do something like that:
Anything[] anything;
//Assign some Instances to anything
foreach(Final final in anything){
//do something with final
}
The result I'd like to get is to be able to do something like that:
Anything[] anything;
//Assign some Instances to anything
foreach(Final final in anything){
//do something with final
}
Your foreach loop suggests this: class Anything : Final { … }.
This obviously turns around the inheritance hierarchy as you planned and named it. (You cannot have cycles in your inheritance relationships).
public class Base<T> : T where T : Anything { …
Let me elaborate on this part for a bit. I'll reduce your example even further to just class Base<T> : T.
This is not possible, for good reason. Imagine this:
class Base<T> : T
{
public override string Frobble()
{
Fiddle();
return "*" + base.Frobble() + "*";
}
}
class A
{
public sealed string Frobble() { … }
}
class B
{
}
class C
{
public virtual string Frobble() { … }
}
abstract class D
{
public abstract void Fiddle();
public virtual string Frobble() { … }
}
class E
{
public void Fiddle() { … }
public virtual string Frobble() { … }
}
You get all kinds of absurd situations if class Base<T> : T were allowed.
Base<A> would be absurd because Frobble cannot be overridden in a derived class.
Base<B> would be absurd because you cannot override a method that
doesn't exist in the base class.
Base<C> doesn't work because there is no Fiddle method to call.
Base<D> would not work because you cannot call an abstract method.
Only Base<E> would work.
How would the compiler ever know how to correctly compile Base<T> and analyse code that depends on it?
The point is that you cannot derive from a class that is not known at compile-time. T is a parameter, i.e. a variable, a placeholder. So class Base<T> : T is basically like saying, "Base<T> inherits from some (unknown) class". Class inheritance is a type relationship that requires both involved types to be known at compile-time. (Actually, that's not a super-precise statement because you can inherit from a generic type such as class SpecialList<T> : List<T>. But at the very least, the derived class has to know what members (methods, properties, etc.) are available in the base class.)
Is this what you want?
sealed public class Final : Base<int>{
}
public class Base<T> {
}
You could only do this if Final would be a generic class as well, like so:
public sealed class Final<T> : Base<T>
Then you can put a type restraint on T as either a class, to allow only reference types as T, or an instance of Base<T>, to allow only types that derive from Base<T>:
public class Base<T> where T : Base<T>
I don't know the context of this question, but I ran into same question with a project where I had to make it possible to extend the base class which is already derived by many others. Like:
abstract class Base {}
class FinalA : Base {}
class FinalB : Base {}
// Now create extended base class and expect final classes to be extended as well:
class BetterBase : Base {}
The solution was to create common ancestor and connect through properties:
abstract class Foundation {}
abstract class Base : Foundation
{
Foundation Final { get; }
}
class FinalA : Foundation {}
class FinalB : Foundation {}
class FinalC : Foundation
{
Foundation Base { get; }
}
// Here's the desired extension:
class BetterBase : Base {}
Now BetterBase has connection to final class and if needed, the final classes could have connection with (Better)Base also, as shown in FinalC class.

Categories

Resources