Три «кита» ООП. Пример 1

Как думает программист, использующий технологию ООП ?
Зачем нужны инкапсуляция, наследование и полиморфизм?

Пусть требуется создать программу, обрабатывающую данные о семьях, имеющих детей.

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: Наш Чат, в котором вы можете обсудить любые вопросы, идеи, поделиться опытом или связаться с администраторами.


Понравилась статья? Поделиться с друзьями:
5 1 голос
Рейтинг статьи
Подписаться
Уведомить о

3 комментариев
Новые
Старые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии

20+ лет назад изучал функциональное программирование, смотрю на это ООП (которое, по идее, должно упрощать понимание структуры программ) — у меня в голове всё только больше путается. Будем смотреть дальше, надеюсь, разберусь на практике. А сайт отличный, автору большое спасибо.

В параграфе 4, в первой строке, обнаружилась опечатка. Думаю вместо метода GrtName(), должно быть GetName().

3
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x