C# 从基类到与方法同名的类调用方法

C# 从基类到与方法同名的类调用方法,c#,methods,C#,Methods,小结:B接收A的呼叫,并自动启动start方法 假设我们有一个类A:A有一个名为Start的函数,该Start函数最初是从另一个类调用的(让我们将该类称为C),一旦调用了它,它应该使用Start(并使用它的基类)调用所有类中的每个方法,使用相同的方法 我们有B:一个使用a作为基类的类,它的任务是从a(最初由C调用)接收Start方法。现在我可以通过直接从A调用B的方法来实现这一点,但在本例中,B可以被命名为任何名称,多个类继承同一个方法 这很有用,因为我不想将所有变量分配给一个启动函数。相反,您

小结:B接收A的呼叫,并自动启动start方法

假设我们有一个类A:A有一个名为Start的函数,该Start函数最初是从另一个类调用的(让我们将该类称为C),一旦调用了它,它应该使用Start(并使用它的基类)调用所有类中的每个方法,使用相同的方法

我们有B:一个使用a作为基类的类,它的任务是从a(最初由C调用)接收Start方法。现在我可以通过直接从A调用B的方法来实现这一点,但在本例中,B可以被命名为任何名称,多个类继承同一个方法

这很有用,因为我不想将所有变量分配给一个启动函数。相反,您可以创建一个允许调用相同函数名的函数

例如:下面是我认为它会是什么样子

class A
{
    public void Start()
    {
        // Call B's Start here...
    }
}

class B : A
{
    public void Start()
    {
        // Receive A's call ... and do stuff here
    }
}


// This time, we also need to access this start method.
// But this class could be named anything
class anotherClass : A
{
    public void Start()
    {
        // Receive A's call
    }
}

class C
{
    static void Main(string[] args)
    {
        A a = new A();

        // Maybe somehow call all start methods here
        a.Start();
    }
}
但正如你们所看到的,在A类中的Start将被调用,但在B类中它永远不会调用Start


在更好的上下文中,我需要一种方法来调用每个类中的所有Start方法。

只需引用基类:

// or maybe you want to override??
public new void Start()
{
  base.Start();
}

在类层次结构中的每个
开始
类中使用它

您从未创建过
B
其他类
对象。因此,无法调用它们的
Start
方法

继承则相反。派生类可以调用其基类成员,因为它知道其祖先并继承其所有成员(字段、属性和方法)。另一端的基类(
A
)不知道它的后代

必须使用可以在派生类中重写的
虚拟
方法。例如:

class A
{
    public virtual void Start()
    {
        Console.WriteLine("Starting A");
    }
}

class B : A
{
    public override void Start()
    {
        base.Start();
        Console.WriteLine("Starting B");
    }
}
现在您可以创建一个
B
对象并调用其
Start
方法

var b = new B();
b.Start();
这将输出:

启动
启动B
因为派生类型与它们的基类型是赋值兼容的,所以您也可以这样做

var list = new List<A> { new B(), new A() };
foreach (A a in list) {
    a.Start();
}
其中前两行来自
B.Start()
,最后一行来自
A.Start()


但这只适用于直接血统中的类。不能从同级调用方法。为什么?让我们举个例子:

class C : A
{
    private string s = "hello";

    public override void Start()
    {
        base.Start();
        Console.WriteLine("Starting C: " + s);
    }
}
假设您可以在
B
中执行类似操作:

sibling(C).Start();

s
的值
“hello”
应该来自哪里?无论是
A
,还是
B
都没有这样的字段,并且从未创建
C
对象。因此,无法满足从所有类调用每个方法的要求。但是如果涉及
a
字段,这将起作用,因为
B
继承此字段。

您不能在未初始化的类上调用方法。因此,除非初始化了B的实例,否则调用
A.Start()
将无法调用
B.Start()
。此外,B应通知A其存在。(除非你会使用反射,但我认为这不是你想要的)

您可以使用自定义委托的事件将B挂接到a:

class Program
{
    static void Main(string[] args) 
    {
        var a = new A();
        var b = new B();
        a.StartHandler += b.Start;
        a.Start();

        // Output:
        // A.Start() starting.
        // B.Start() called.
        // A.Start() ending.
    }
}

class A
{
    public delegate void StartMethod();
    public event StartMethod StartHandler;

    public virtual void Start()
    {
        Console.WriteLine("A.Start() starting.");
        if (this.StartHandler != null)
        {
            this.StartHandler();
        }
        Console.WriteLine("A.Start() ending.");
    }
}

class B : A
{
    public override void Start()
    {
        Console.WriteLine("B.Start() called.");
    }
}
另一个更简单的选择可能是(取决于您想要什么),通过简单继承以另一种方式进行。如果创建B的实例,可以将其视为A的实例。因此,您不必知道您实际上在使用B类型:

class A
{
    public virtual void Start() => Console.WriteLine("A.Start()");
}

class B : A
{
    public override void Start()
    {
        Console.WriteLine("B.Start()");
        base.Start();
    }
}

// usage:
A a = new B();
a.Start();

// Output:
// B.Start()
// A.Start();

谢谢,我现在知道我必须添加脚本的每个实例,并循环每个实例,直到它找到具有相同基类的类型。每个startable类都可以实现一个
IStartable
接口。这些对象可以订阅全局启动事件。或者,您可以在所有类的构造函数中开始。