定义抽象方法而不指定参数

发布于 2024-10-15 04:45:14 字数 142 浏览 1 评论 0原文

我正在编写一个带有抽象方法的抽象类(因此,从它继承的所有类都必须实现该方法)。但是,我不想指定该方法必须使用的参数,因为每个方法可能采用不同的参数或不采用参数。只有名称和返回值应该相同。

有没有办法在 C# 中做到这一点?

感谢您的帮助!

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!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

獨角戲 2024-10-22 04:45:14

不,这样做是没有意义的。如果您没有声明参数,则您将无法调用仅提供对基类的引用的方法。这就是抽象方法的意义所在:让调用者不用关心具体的实现,而是给他们一个 API 来使用。

如果调用者需要知道确切的方法签名,那么你已经将该调用者绑定到具体的实现,从而使抽象本质上毫无用处。

也许如果您可以提供更多详细信息,我们可以建议更合适的方法?例如,您可以使类型通用:

public class Foo<T>
{
    public abstract void Bar(T t);
}

具体子类型可以是通用的,或者例如从Foo派生。

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.

不顾 2024-10-22 04:45:14

不,你为什么需要它?也许命令设计模式可以在这里提供帮助。

No. Why do you need it? maybe the Command Design Pattern can help here.

月牙弯弯 2024-10-22 04:45:14

你想做的是代码味道。

更好的模式是让您的抽象类实现 ISupportInitialize,然后有一个抽象的 Act() 方法。

这个想法是,在调用 BeginInitEndInit 之间,当您的孩子键入准备采取行动时,收集您试图塞入随机类型和数字的不同信息位的论点。配置完成后,调用 EndInit(此处验证)即可调用抽象 Act()

另外,请不要这样做:

public abstract void Act(params object[] arguments);

如果你这样做,人们会追捕你。

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.

水溶 2024-10-22 04:45:14

不,没有。

要重写方法,您必须匹配方法签名。这包括方法名称和格式参数。

No, there isn't.

To override a method, you must match the method signature. This includes the method name and format parameters.

青柠芒果 2024-10-22 04:45:14

这个问题需要更多关于在这里做什么的例子,所以这是一个。我的具体场景是我从工厂获取抽象 ActionBaseClass 的具体实例,并且我需要使用特定于我的场景的参数在该实例上调用一些 DoAction() 函数。

以下是这些类的定义:

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

观察 MyConcreteInstance.DoAction() 如何拥有特定场景所需的参数。请注意,此函数不会实现/覆盖 ActionsBaseClass.DoAction,在本例中,这只是向开发人员提示其希望具体类型实现的函数名称。

我像这样从工厂获取实例:

var myA = somethingA;
var myB = somethingB;
var myC = somethingC;

// `SomeFactory.Create` returns the instance as `ActionsClassBase`
var myAction = SomeFactory.Create(typeof(MyConcreteInstance)) as MyConcreteInstance;

我正在转换为具体实例的类型,因为在这种情况下我知道它应该是什么,并且我有需要调用 DoAction 的参数值其上(myAmyBmyC)。我们需要一些对象来保存这些参数并将它们传递到具体实例的操作中。

这里的技巧是创建一个解析器对象来为我们完成工作。我们为要使用的所有具体实例创建一个抽象解析器,并为我们的特定类创建一个特定解析器:

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

现在我可以创建解析器的一个实例,在该实例上我可以使用所需的参数调用 DoAction

// 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);

最后,我可以通过解析器调用该操作:

myActionResolver.DoAction();

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();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文