Практическое применение object slicing C#(Присваивание объекта производного класса переменной базового класса)
На протяжении месяца мучаюсь вопросом о присвоении ссылке базового класса ссылку на класс наследника. К примеру
class Person
{
public string Name;
}
class Worker:Person
{
public void Work()
{
Console.WriteLine("Мало денег,надо работать")
}
}
Можно объявить объект класса Person
и присвоить ему объект класса Worker
.
Person Nikita= new Worker();
Функционал у нашего Никиты будет обрезан, и из этого исходит вопрос, для чего это может пригодиться на практике, если мы могли присвоить Никите сразу класс Person
и по идее получили бы тоже самое?
Ответы (2 шт):
Самый простой случай
...это когда у вас есть множество классов наследовавшие от Person
и все они разные. Но они все ещё Person
и нужно узнать имя каждого:
class Person
{
public string Name;
}
class Worker: Person
{
public void Work()
{
Console.WriteLine("Мало денег,надо работать");
}
}
class Student: Person
{
public void Teach()
{
Console.WriteLine("Мало знаний,надо учиться");
}
}
class Program
{
static void Main(string[] args)
{
Person Nikita = new Worker();
Person Vasya = new Student();
Person[] people = [Nikita, Vasya];
foreach (Person person in people)
{
Console.WriteLine(person.Name);
}
}
}
Почему по другому нельзя?
К примеру, если мы создадим экземпляр Person
потом мы не сможем использовать его как Worker
:
class Program
{
static void Main(string[] args)
{
Person Nikita = new Person();
Worker NikitaAsWorker = (Worker) Nikita; // Вот эта конвертация приведет к ошибке
NikitaAsWorker.Work();
}
}
А вот так можно:
class Program
{
static void Main(string[] args)
{
Person Nikita = new Worker();
Worker NikitaAsWorker = (Worker) Nikita;
NikitaAsWorker.Work();
}
}
Присвоение объекта производнго класса переменной базового класса — это ключевая возможность, которую предоставляет полиморфизм в C#. Когда вы создаете переменную базового класса и присваиваете ей объект производного класса, вы получаете возможность рабтать с объектами через общий интерфейс базвого класса
Это особенно полезно, когда нужно обрабатывать коллекцию различных объектов, у которых есть общие свойства, но разные реализации методов.
Person Nikita = new Worker { Name = "Nikita" };
Person Vasya = new Student { Name = "Vasya" };
Person[] people = { Nikita, Vasya };
foreach (Person person in people)
{
Console.WriteLine(person.Name);
}
Здесь все объекты хранятся как тип Person, но на самом деле они могут быть любыми производными от Person классами. Это упрощает управление объектами и кодирование. Если вам необходимо вызвать метод, специфичный для производного класса, вы можете использовать приведение типов:
Worker worker = Nikita as Worker;
worker?.Work();
Таким образом, функционал не теряется, а управление становится гибче.
В случае с object slicing в C++ происходит копирование только базвой части объекта, тогда как в C# это не актуально, так как переменные класса хранят ссылки на объекты. Поэтому вам не нужно беспокоиться о том, что функционал будет "обрезан"