c# runtime polymorphism with abstract base class - c#

I am trying to clean up an existing code base, and am having trouble with using a generic reference name to the different derived classes of an abstract class.
For instance:
public abstract class Base<T> : Utilities.CommonRequiredObject
{
protected List<T> RawContents = new List<T>();
.
.
public abstract void LoadContents(List<T> Contents); // Each Class needs to load and process differently
protected List<T> Contents;
public virtual void DoSomething() // Default here for common use. Defined in Each class for its specifics (if needed)
{
...
}
public abstract List<T> FunctionToGetContents();
}
public class FOO : Base<string>
{
public override void DoSomething() ...
public override List<string> FunctionToGetContents() ...
}
public class BAR : Base<byte>
{
public override void DoSomething() ...
public override List<byte> FunctionToGetContents() ...
}
Main Logic to try to use common variable. I want to create a new class to use, but want to use it then in a runtime polymorphic way. As the classes have the common functionality, and have overrides where needed, I want to be able to create an instance, and then use it:
IE: Base<T> ObjectToUse;
This way, I can simply refer to the ObjectToUse in the following code and call common methods. As I inherited some common routines from another base class, I am not sure if I can use an interface or not.
if(variable)
{
FOO ObjectToUse = new FOO();
}
else
{
BAR ObjectToUse = new BAR();
}
ObjectToUse.LoadContents(ObjectToUse.FunctionToGetContents());
ObjectToUse.DoSomething();
...
Edit:
Based on the comments I received quickly (thanks again everyone) would it be better than to remove the Generic (Base<T>) and have the classes all of type Base(), then I could define the ObjectToUse simply as Base ObjectToUse; I believe.

This cannot be done.
By utilizing a reference that requires a generic type parameter, you must give it one. You could utilize dynamic here so that the type is run-time evaluated, but thats the best you will get.
Even utilizing something like a template method pattern, you would need to specify the generic type argument. If you just want the DoSomething method for this, it would need to be promoted to a higher base class (or an interface) so you could hold a reference to that type, and call that (non-generic) function.
To your comment, the solution I would take is this; refactor the common code into a template method pattern within the base class. Then have the "triggering" function be a non-generic inherited member from a non-generic base class (or interface). Now, you can hold a reference to that type, and invoke the template method to cause the other calls to occur.
public void DoAwesomeStuff() //inherited from non-generic parent or interface
{
LoadContents(FunctionToGetContents());
DoSomething();
}
Then:
IDoesAwesomeStuff ObjectToUse = new FOO();
ObjectToUse.DoAwesomeStuff();

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.

Creating a generic interface in C#

I know that the title may be confusing (or even misleading), but I'm planning to create an interface which is generic, and it should implement a method involving a generic parameter.
When implemented in class AFirst, it should have a method MyMethod<A>() that returns the type A, and when implemented in class BFirst, it should have a method MyMethod<B>() that returns type B. I need this functionality as there is an inheritance relationship between A and B (and MANY others) and I need a generic method that I can call with any of the base classes.
If it was confusing, have a look at what I want to do:
Consider B derives from A.
Consider AFirst and BFirst implement IMyInterface<A> and IMyInterface<B> respectively:
BFirst mySecondObj = new BFirst();
A myA = BFirst.MyMethod<A>();
B myB = BFirst.MyMethod<B>();
I need access to the MyMethod templates for the base classes to, so when I instantiate the BFirst instance, I can call either MyMethod for A or B. I'm building a template system and think these AFirst and BFirst are the templates, and MyMethod acts like a factory method. I will have a big hierarchy, and the project needs to be extensible by deriving even more classes from my base class A, so I can't just create seperate interfaces or methods for each of them.
I tried this:
interface IMyInterface<T> where T : A
{
T GetNewInstance<T>();
}
and I tried to implement this way, but I'm getting it as created like this when I click implement:
class AFirst : IMyInterface<A>
{
public T GetNewInstance<T>()
{
throw new NotImplementedException();
}
}
Didn't make sense to me in the way that I've specified the T type to be A, but it still implements as T. For example, it will go like this (below is how I want it to happen)
class AFirst : IMyInterface<A>
{
public A GetNewInstance<A>()
{
throw new NotImplementedException();
}
}
class BFirst : AFirst, IMyInterface<B>
{
public B GetNewInstance<B>()
{
throw new NotImplementedException();
}
}
and from outer code, call the sample as in the beginning of my question:
BFirst myBFirst = new BFirst();
A a = BFirst.GetNewInstance<A>(); //calls AFirst's method and returns A
B b = BFirst.GetNewInstance<B>(); //calls BFirst's method and returns B
How is this possible?
Thanks,
Can.
In your generic interface you define a generic method. I think that's where the confusion is. It should be a normal method that returns your generic type. I.e.
interface IMyInterface<T> where T : A
{
T GetNewInstance();
}
This will get implemented as
class AFirst : IMyInterface<A>
{
public A GetNewInstance()
{
throw new NotImplementedException();
}
}
which I'm guessing is what you want.
You are possibly over complicating this. You could consider a Template pattern. The base class is abstract and defines an overridable method. Classes inheriting from this base class then provide implementations of this method.
You can still use generics and an interface but this pattern is probably the basis you would need to start from.
Edit:
public abstract class ABase<T>
{
public abstract T MyMethod();
}
public class A : ABase<A>
{
public override A MyMethod()
{
throw new NotImplementedException();
}
}
public class B : A
{
}
And to implement an interface, this would be
public interface IHasMethod<T>
{
T MyMethod();
}
public abstract class ABase<T> : IHasMethod<T> ...

Why must an C# interface method implemented in a class be public?

I have a class which inherits an interface. An interface member method is implemented in my class without an access modifier (so, by default it's private ) .
I am getting the error "cannot implement an interface member because it is not public".
Why it is not allowed? Can't I override the accessibility?
Here's an example of why it doesn't make sense to be able to override the visibility:
interface someI
{
void doYourWork();
}
public class A : someI
{
public void doYourWork()
{
//...
}
}
public class B : someI
{
private void doYourWork()
{
//...
}
}
void Main()
{
List<someI> workers = getWorkers();
foreach(var worker in workers)
worker.doYourWork();
}
What happens when your worker is of type B? You're calling a method as if it were public, but it's a private method. If you want this functionality, then it's not really a private method is it?
If you only want it to be public when referenced through your interface, then you can define it as such:
public class B : someI
{
void someI.doYourWork()
{
//...
}
}
And you end up with this:
var b = new B();
b.doYourWork(); // Not accessible
((someI)b).doYourWork(); // Accessible
Methods have to be implemented public because they have to be callable through the interface, thus from where the interface is accessible as a type.
You have a few options here to "change" the visibility of that method. Given:
public interface IFoo
{
bool IsFoo();
}
A. Implement the method explicitly
public class Foo : IFoo
{
bool IFoo.IsFoo() { return true; }
}
The method will only be available through the interface (IFoo in this case.)
B. Change the visibility of the interface
Define the interface as internal instead of public. As a consequence, however, Foo will have to be internal too.
Requiring that an interface implementation be public is simply a logical requirement. When you implement an interface, you're telling the compiler "Hey I implement every method on this interface". So making the method private makes it no longer accessible - and logically not implemented. Interfaces serve as a contract to code that uses your object saying you can always call any method defined in the interface on my object. If the implementing method were private, that would not longer be true.
If you want to hide your implementation from, say Intellisense, then you can simply implement the method explicitly as #Bryan mentions.

Categories

Resources