Как думает программист, использующий технологию ООП ?
Зачем нужны инкапсуляция, наследование и полиморфизм?
Пусть требуется создать программу, обрабатывающую данные о семьях, имеющих детей.
1. Начнем с традиционной семьи (мать-отец-ребенок).
а) cоздадим класс MFC, содержащий следующие поля — имена матери, отца и ребенка, назовем эти поля соответственно:
mother, father, child;
б) в классе необходим конструктор MFC(string m, string f, string c), который будет задавать три поля нашего класса;
в) создадим метод класса void Output(), который будет выводить данные о семье (пока только имена);
г) добавим также метод, возвращающий только имя ребенка GetChild();
В консольное приложение кроме файла Program.cs добавим файл Class2.cs (имя может быть любое), куда поместим следующий текст:
using System; namespace МатьОтецРебенок { // Инкапсуляция в классе MFC public class MFC { protected string mother; protected string father; protected string child; public MFC(string m, string f, string c) { mother = m; father = f; child = c; } // возврат имени ребенка public virtual string GetChild() { return child; } // вывод имен членов семьи public virtual void Output() { Console.WriteLine("Mать: " + mother + " отец: " + father); Console.WriteLine("Ребенок: " + child); } // Рисование разграничительной линии (пригодится) public virtual void Tir() { Console.WriteLine("_____________________________"); } } }
Комментарий. Поля класса MFC объявим защищенными (protected), так как они будут наследоваться в дочерних классах. Для извлечения всех полей будет использоваться метод void Output() как public, а также и как virtual с учетом его дальнейшей перегрузки. Заметим, что метод string GetChild() имеет такие же модификаторы.
Проверим, как это работает. Для этого добавим в метод Main() три оператора:
using System; namespace МатьОтецРебенок { class Program { static void Main() { // R - объект родительского класса MFC R = new MFC("Барбара", "Борис", "Бэлла"); R.Output(); R.Tir(); // разделитель информации } } }
Результат:
Mать: Барбара отец: Борис
Ребенок: Бэлла
_____________________________
2. Что делать, если в семье 2 ребенка? Переделывать исходный класс, или наследовать от него другой? В ООП выбирают второй вариант.
Нам нужно будет только добавить поле child2, увеличить на 1 список параметров конструктора, изменив и его. Далее выполним перегрузку двух других методов исходного класса, при этом их имена не изменяются — помните, что означает полиморфизм? Тогда новый дочерний класс назовем DMFC:
// Наследование класса MFC (3 + 1) public class DMFC : MFC { protected string child2; // + 2-й ребенок // конструктор класса наследуется вот так: public DMFC(string m, string f, string c, string d): base (m, f, c) { child2=d; } // перегрузка метода (модификатор override) public override string GetChild() { return child + ", " +child2; } // Перегрузка метода - полиморфизм (добавим 2 ребенка) public override void Output() { base.Output(); // используем метод родительского класса Console.WriteLine("Второй ребенок: " + child2); // только добавление } }
Выполним проверку, добавив в Main( ) три оператора:
// D - объект дочернего класса DMFC D = new DMFC("Валентина", "Виктор", "Владимир", "Валентина"); D.Output(); D.Tir();
Результат:
Mать: Барбара отец: Борис
Ребенок: Бэлла
_____________________________
Mать: Валентина отец: Виктор
Ребенок: Владимир
Второй ребенок: Валентина
_____________________________
Как Вы видите, добавился вывод имени второго ребенка.
3. Но если Вам теперь потребуется добавить еще одно поле — фамилию семьи и метод для возврата фамилии семьи GetName( ), то поступайте также, создайте дочерний класс (класс-внук) от DMFC, назвав его, например, VMFC:
// Наследование класса DMFC (4 + фамилия) public class VMFC: DMFC { protected string name; // + фамилия семьи public VMFC(string m, string f, string c, string d, string n): base (m, f, c, d) { name = n; } // Перегрузка метода - полиморфизм (добавим фамилию) public override void Output() { Console.WriteLine("Фамилия семьи: {0}", name); base.Output(); // будет использоваться метод класса DMFC } public string GetName() { return name; } }
Выполним проверку, добавив в Main( ) три оператора:
// V объект класса - внук, наследуется от DMFC VMFC V = new VMFC("Прасковья", "Петр", "Павел", "Паулина", "Петровы"); V.Output(); V.Tir();
Результат:
Mать: Барбара отец: Борис
Ребенок: Бэлла
_____________________________
Mать: Валентина отец: Виктор
Ребенок: Владимир
Второй ребенок: Валентина
_____________________________
Фамилия семьи: Петровы
Mать: Прасковья отец: Петр
Ребенок: Павел
Второй ребенок: Паулина
_____________________________
4. Для чего могут пригодиться методы GetChild( ) и GetName( )? А вот для чего. Добавив в Main( ) еще 4 оператора:
// Дети и фамилия Console.WriteLine("Дети: " + R.GetChild()); Console.WriteLine("Дети: " + D.GetChild()); Console.WriteLine("Дети: " + V.GetChild()); Console.WriteLine("Фамилия: " + V.GetName()); V.Tir();
Результат:
Mать: Барбара отец: Борис
Ребенок: Бэлла
_____________________________
Mать: Валентина отец: Виктор
Ребенок: Владимир
Второй ребенок: Валентина
_____________________________
Фамилия семьи: Петровы
Mать: Прасковья отец: Петр
Ребенок: Павел
Второй ребенок: Паулина
_____________________________
Дети: Бэлла
Дети: Владимир, Валентина
Дети: Павел, Паулина
Фамилия: Петровы
_____________________________
Как Вы видите, с помощью этих методов Вы получаете доступ к защищенным полям классов.
Вот как в целом записывается текст Program.cs (приводится для контроля):
// Инкапсуляция, Наследование, Полиморфизм // на примере разного состава семей и полей // Классы MFC, DMFC, VMFC - в файле Class2.cs // (С) c-sharp.pro, 2020 using System; namespace МатьОтецРебенок { class Program { static void Main() { // R - объект родительского класса MFC R = new MFC("Барбара", "Борис", "Бэлла"); R.Output(); R.Tir(); // разделитель информации // D - объект дочернего класса DMFC D = new DMFC("Валентина", "Виктор", "Владимир", "Валентина"); D.Output(); D.Tir(); // V объект класса - внук, наследуется от DMFC VMFC V = new VMFC("Прасковья", "Петр", "Павел", "Паулина", "Петровы"); V.Output(); V.Tir(); // Дети и фамилия Console.WriteLine("Дети: " + R.GetChild()); Console.WriteLine("Дети: " + D.GetChild()); Console.WriteLine("Дети: " + V.GetChild()); Console.WriteLine("Фамилия: " + V.GetName()); V.Tir(); } } }
Как Вы считаете, достаточно легко воспринимается Вами текст метода Main( )?
NEW: Наш Чат, в котором вы можете обсудить любые вопросы, идеи, поделиться опытом или связаться с администраторами.
20+ лет назад изучал функциональное программирование, смотрю на это ООП (которое, по идее, должно упрощать понимание структуры программ) — у меня в голове всё только больше путается. Будем смотреть дальше, надеюсь, разберусь на практике. А сайт отличный, автору большое спасибо.
В параграфе 4, в первой строке, обнаружилась опечатка. Думаю вместо метода GrtName(), должно быть GetName().
VAL, спасибо, исправил в тексте.