Polymorphism, using methods of child classes - c#

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.

Related

Interface vs Class method parameter ambiguity

I am certain that I simply do not know the name for what I am trying to do, otherwise my googling would be more successful. I currently only find results pertaining to interfaces with same named methods.
I have a few classes that inherit from a common base class and some implement an interface. I have methods accepting the base class or the interface as a parameter. I cannot compile since this causes ambiguity with the error
the call is ambiguous between the following methods or properties: DoThings(IQueryable<A>) and DoThings(IQueryable<B>)` on the call in ConcreteExecutionClass.
Furthermore, generics won't work because type constraints on generics do not make a unique method signature.
Is there a way (or an acceptable pattern) to force the execution to a specific method based on parameter types?
public abstract class A {
// some properties
}
public class ConcreteA : A {
// full implementation
}
public interface B {
// a property
}
public class ConcreteAB : A, B {
// full implementation
}
public abstract class ExecutionClass {
public IQueryable<A> DoThings(IQueryable<A> content){
return A.method().AsQueryable();
}
public IQueryable<B> DoThings(IQueryable<B> content){
return B.interfaceRequiredMethod().method().AsQueryable();
}
}
public class ConcreteExecutionClass : ExecutionClass {
public void Program(){
var objectList = new List<ConcreteAB>{/*....*/};
DoThings(objectList);
}
}
Each of the concrete classes has a class managing linq queries on lists of objects, which each call DoThings(). The goal is to keep the actual implementation of DoThings() transparent to the concrete classes.
I have attempted covariance in the interface, however have been unable to avoid inheriting A which forces down the first code path.
The code above is a simplification of the actual implementation. There are about 10 classes deriving solely from A and 4 deriving from A and B.
I simply created an abstract hierarchy where abstract A is the base and there are 2 abstract classes inheriting from it.

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.

How to require subtypes of an abstract class to implement a static instantiator?

public abstract class A
{
// constructors omitted
public abstract A Create(SomeData data);
}
public class B : A
{
// constructors omitted
public override A Create(SomeData data)
{
return new B(data);
}
}
What I want is to be able to make the Create method static, so that I can get an instance of B without having to create a useless instance with an empty constructor. (If you're wondering why, A is actually a generic type of the form A<TFoo, TBar>, where TBar corresponds to the derived types. As we all know, you can't instantiate a generic type using a constructor that takes any arguments.)
I am already aware that static methods are decoupled from the object hierarchy, only relying on the name of the type. That means I can't have Create as an abstract method that I force all descendants to implement. Is there another way I can implement this pattern?
Something like this might work, depends on your requirements
public abstract class A
{
public string Data { get; set; }
public static T Create<T>(string data) where T : A, new()
{
return new T() { Data = data };
}
}
public class B : A { }
then can do
A foo = A.Create<B>("foo");
There is simply no way to do this. Inheritance is based off of instance methods in C# and has no equivalent feature for static methods. Another way to implement this pattern though is to require a lambda in lieu of a static method.
For example (you mentioned the actual type was A<TFoo, TBar>)
void UseIt<TFoo, TBar>(A<TFoo, TBar> p, Func<SomeData, TBar> func) {
TBar b = func();
...
}
The consumer doesn't care if Create is static, instance or even called create. Generally all they care about is having a function which takes a SomeData and returns a TBar. Delegates fit this pattern exactly.

Generic base class with multiple children

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

How to use a class as the base, but hide the class type publically?

I am currently just exposing the properties through a generic interface e.g.
public interface IBaseClass
{
int ID { get; set; }
}
internal class MyBaseClass : IBaseClass
{
public MyBaseClass() { }
public int ID { get; set; }
}
public class MyExposedClass : IBaseClass
{
private MyBaseClass _base = new MyBaseClass();
public int ID
{
get { return _base.ID; }
set { _base.ID = value; }
}
}
Then in my main application I can do:
IBaseClass c = new MyExposedClass();
c.ID = 12345;
But can't do:
MyBaseClass b = new MyBaseClass();
This is my desired behaviour.
However, I was just wondering if this is the correct approach? Or if there was a better way?
If you only want to prevent instantiation you could make MyBaseClass abstract (make it's constructor protected as well - it is a good design) and have MyExposedClass derive from it. If you want to completely hide the type your approach seems fine.
This look fine to me. Making small interfaces makes it easier to write decoupled code.
I don't know if this will help, but you can make your base class protected internal. This would mean that any internal class has access to it as if it were public, or any class (from within and without the assembly) can subclass the base class. It won't prevent people from implementing their own sub class though.
Alternatively, exposing through an Interface would be the best way I'd think.
For this you can opt for explicit implementation like this:
public interface IBaseClass
{
int ID { get; set; }
}
internal class MyBaseClass : IBaseClass
{
public MyBaseClass() { }
public int IBaseClass.ID { get; set; }
}
public class MyExposedClass : IBaseClass
{
private MyBaseClass _base = new MyBaseClass();
public int IBaseClass.ID
{
get { return _base.ID; }
set { _base.ID = value; }
}
}
You can refer to a similar post C# Interfaces. Implicit implementation versus Explicit implementation
Make your base class abstract.
You could expose the interface as public, implement an internal sealed implementation of that class, and use a factory approach to build instances of the desired interface. That way the client will never know when you change your implementation, or if you have multiple implementations of the same base interface plugged in the factory. You could also eliminate the set accessors in the interface and put them in the internal implementation to only expose the properties to the outside world. That way the exterior code has to make less assumptions over your implementation and you are better isolated. Please correct me if I'm having a poor/bad image of this approach.
Edit: The factory would be public and you'd need some sort of "transfer object" to pass data to the factory. That transfer object implementation would be public, together with it's interface.
Your example seems to include a poor example of taking advantage of inheritence. Since you included a single property it and couldnt come up with a better example i am guessing that its real. I would suggest in this case forget the base class and stick the property on the derived.

Categories

Resources