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