Вызов метода из базового класса в класс с тем же именем, что и у метода

#c# #methods

#c# #методы

Вопрос:

Итог: B получает вызов от A и автоматически запускает метод start

Допустим, у нас есть класс A: A имеет функцию с именем Start , эта функция start изначально вызывается из другого класса (давайте называть этот класс C), и как только она вызвана, она должна вызывать каждый метод из всех классов, использующих Start (и использующих его базовый класс), с тем же методом.

И у нас есть B: класс, использующий A в качестве базового класса, его задача — получить метод Start от A (первоначально вызванный C). Теперь я мог бы просто сделать это, вызвав метод B непосредственно из A, но в этом случае 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();
    }
}
  

Но, как вы можете видеть, Start в классе A будет вызван, но он никогда не вызовет start в классе B.

В лучшем контексте мне нужен способ вызова всех методов запуска из каждого класса.

Ответ №1:

Просто используйте ссылку на базовый класс:

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

Используйте его в каждом Start классе ниже по иерархии классов

Ответ №2:

Вы никогда не создавали объект B или anotherClass . Поэтому их Start метод не может быть вызван.

Наследование работает наоборот. Производный класс может вызывать членов своего базового класса, потому что он знает своего предка и наследует все его члены (поля, свойства, методы). Базовый класс ( A ) на другой стороне не знает своих потомков.

Вы должны использовать virtual методы, которые вы можете override использовать в производных классах. Пример:

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

Это приведет к:

 Starting A
Starting B
  

Поскольку производные типы совместимы по назначению с их базовыми типами, вы также можете сделать что-то вроде этого

 var list = new List<A> { new B(), new A() };
foreach (A a in list) {
    a.Start();
}
  
 Starting A
Starting B
Starting A
  

откуда взяты две первые строки 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();
  

Откуда должно взяться значение "hello" of s ? Ни у A , ни у B такого поля нет, и C объект никогда не создавался. Таким образом, ваше требование вызывать каждый метод из всех классов не может быть выполнено. Но если бы было задействовано поле A , это сработало бы, так как B наследует это поле.

Комментарии:

1. Спасибо, теперь я знаю, что мне нужно добавлять каждый экземпляр скрипта и выполнять цикл для каждого из них, пока он не найдет тип с тем же базовым классом.

2. У вас есть много вариантов. Каждый запускаемый класс мог бы реализовать IStartable интерфейс. Объекты могут подписаться на глобальное событие запуска. Или, может быть, вы могли бы выполнить запуск в конструкторе всех классов.

Ответ №3:

Вы не можете вызывать методы в неинициализированных классах. Таким образом, вызывающий A.Start() не сможет вызвать B.Start() , если экземпляр B не инициализирован. Кроме того, 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();