Reputation: 769
I am writing an abstract class with an abstract method (thus, all classes inheriting from it must implement that method). However, I do not want to specify the parameters which the method must use, as each method may take in different or no parameters. Only the name and return value should be the same.
Is there a way to do this in C#?
Thanks for any help!
Upvotes: 21
Views: 21453
Reputation: 3904
This question needed some more examples of what do do here, so here's one. My specific scenario is I get the concrete instance of an abstract ActionBaseClass
from a factory and I need to call some DoAction()
function on that instance with parameters specific to my scenario.
Here's the definitions of the classes:
public abstract class ActionsClassBase
{
// Hint for the funciton we want on our concrete instances
public virtual bool DoAction() =>
throw new NotImplementedException();
}
public class MyConcreteInstance : ActionsClassBase
{
public bool DoAction(object a, string b, int c)
{
// your implmentation
}
}
Observe how MyConcreteInstance.DoAction()
has the parameters it needs for the specific scenario. Note that this funcion doesn't implement/override ActionsBaseClass.DoAction
, which in this case is just a hint to the developer of the name of the function it wants the concrete types to implement.
I get my instance from the factory like this:
var myA = somethingA;
var myB = somethingB;
var myC = somethingC;
// `SomeFactory.Create` returns the instance as `ActionsClassBase`
var myAction = SomeFactory.Create(typeof(MyConcreteInstance)) as MyConcreteInstance;
I'm casting to my concrete instance's type because in this scenario I know what it's supposed to be, and I have values for the parameters I need to call DoAction
on it (myA
, myB
, and myC
). We need some object that will hold these parameters and pass them into the action on the concrete instance.
The trick here is to create a resolver object that will do the work for us. We create an abstract resolver for all our concrete instances to use, and a specific resolver for our specific class:
public abstract class DoActionResolver
{
// Function with the same parameters and return type as in `AbstractClassBase`
public abstract bool DoAction();
}
public class MyConcreteInstanceDoActionResolver : DoActionResolver
{
MyConcreteInstance _instance;
object _a;
string _b;
int _c;
public MyConcreteInstanceDoActionResolver(MyConcreteInstance instance, object a, string b, int c)
{
_instance = instance
_a = a;
_b = b;
_c = c;
}
public override bool DoAction() =>
_instance.DoAction(_a, _b, _c);
}
Now I can create an instance of my resolver on which I can call DoAction
with the parameters I need:
// I already know what I need to call the action with on my instance in this scenario.
// Lets assume we are storing them in variables with names myA, myB, and myC
var myActionResolver = new MyConcreteInstaceDoActionResolver(myAction, myA, myB, myC);
Finally, I can call the action through my resolver:
myActionResolver.DoAction();
Upvotes: -1
Reputation:
What you're trying to do is a code smell.
A better pattern would be to have your abstract class implement ISupportInitialize, and then have an abstract Act()
method.
The idea is that in between calls to BeginInit
and EndInit
is when your child types prepare to act, gathering the different bits of info you are trying to cram into random types and numbers of arguments. Once configured, and EndInit
is called (validate here) the abstract Act()
can be called.
Also, please PLEASE do not do this:
public abstract void Act(params object[] arguments);
People will hunt you down if you do something like this.
Upvotes: 2
Reputation: 18286
No. Why do you need it? maybe the Command Design Pattern can help here.
Upvotes: 4
Reputation: 498972
No, there isn't.
To override a method, you must match the method signature. This includes the method name and format parameters.
Upvotes: 1
Reputation: 1500225
No, and it would be pointless to do so. If you didn't declare the parameters, you wouldn't be able to call the method given only a reference to the base class. That's the point of abstract methods: to allow callers not to care about the concrete implementation, but to give them an API to use.
If the caller needs to know the exact method signature then you've tied that caller to a concrete implementation, making the abstraction essentially useless.
Perhaps if you could give more details, we could suggest a more appropriate approach? For example, you might be able to make the type generic:
public class Foo<T>
{
public abstract void Bar(T t);
}
Concrete subtypes could either also be generic, or derive from Foo<string>
for example.
Upvotes: 23