C#. Примеры создания иерархий классов с использованием наследования

C#. Примеры создания иерархий классов с использованием наследования

В данной теме рассматривается два примера разработки классов с использованием наследования. Каждый пример содержит комментарии с объяснениями особенностей работы соответствующего фрагмента кода. При создании иерархий классов полиморфизм не используется.
Тема будет полезна начинающим программистам при изучении основ программирования классов, использующих наследование.


Содержание


1. Пример создания иерархии классов. Классы Student, Aspirant

В примере демонстрируется

  • использование модификатора доступа protected при наследовании;
  • использование ключевого слова base в случае вызова конструктора базового класса.
1.1. Условие задачи

Создать базовый класс Student, который будет содержать информацию о студенте (фамилия, курс обучения, номер зачетной книги). С помощью механизма наследование реализовать класс Aspirant (аспирант – студент, который готовится к защите кандидатской диссертации). Класс Aspirant есть производным от класса Student.
В классах Student и Aspirant необходимо реализовать следующие элементы:

  • конструкторы классов с соответствующим количеством параметров. В классе Aspirant для доступа к методам класса Student нужно использовать ключевое слово base;
  • свойства get/set для доступа к полям класса;
  • метод Print(), который выводит информацию о содержимом полей класса.

 

1.2. Решение. Текст программы

Задача решается для приложения типа Console Application. Ниже приведен полный текст программы.

using static System.Console;

namespace ConsoleApp1
{
  // Базовый класс Student, содержит информацию о студенте
  public class Student
  {
    // 1. Поля класса - объявленные как protected - видимы в производных классах,
    // и невидимы из экземпляра класса
    protected string name; // Фамилия и имя студента
    protected int course; // Курс обучения
    protected string gradeBook; // Номер зачетной книги

    // 2. Конструктор класса с 3 параметрами
    public Student(string Name, int course, string gradeBook)
    {
      this.Name = Name;
      this.course = course;
      this.gradeBook = gradeBook;
    }

    // 3. Свойства доступа к полям класса
    public string Name
    {
      get { return name; }
      set { name = value; }
    }

    public int Course
    {
      get { return course; }
      set { course = value; }
    }

    public string GradeBook
    {
      get { return gradeBook; }
      set { gradeBook = value; }
    }

    // 4. Метод Print() - вывести значения полей на экран
    public void Print()
    {
      WriteLine("The values of fields are:");
      WriteLine($"Name = {name}");
      WriteLine($"Course = {course}");
      WriteLine($"GradeBook = {gradeBook}");
    }
  }

  // Класс Aspirant - наследует возможности класса Student
  public class Aspirant : Student
  {
    // 1. Внутреннее поле класса
    protected string topic; // Тема кандидатской диссертации

    // 2. Конструктор класса Aspirant - с помощью ключевого слова base обращается
    // к конструктору базового класса Student
    public Aspirant(string name, int course, string gradeBook, string topic) :
        base(name, course, gradeBook)
    {
      // Можно изменять protected-члены базового класса
      base.name = name; // доступ к полю name класса Student с помощью base
      this.course = course; // доступ к полю course класса Student с помощью this
      this.gradeBook = gradeBook;

      this.topic = topic; // инициализация внутреннего поля класса Aspirant
    }

    // 3. Свойство для доступа к полю topic
    public string Topic
    {
      get { return topic; }
      set { topic = value; }
    }

    // 4. Метод Print() - печать полей класса Aspirant
    // Имя данного метода перекрывает имя метода Student.Print(),
    // поэтому перед именем метода указывается new
    public new void Print() // new - переопределение метода базового класса
    {
      base.Print(); // вызвать метод Print() базового класса
      WriteLine($"Topic = {topic}");
    }
  }

  class Program
  {
    static void Main(string[] args)
    {
      // Демонстрация работы с классами Student и Aspirant

      // 1. Объявить экземпляр класса Student
      Student st1 = new Student("Ivanov I.I.", 2, "0519");

      // 2. Вывести поля класса Student
      WriteLine("The instance of st1:");
      st1.Print();

      // 3. Объявить экземпляр класса Aspirant
      // При объявлении используется свойство get экземпляра st1
      Aspirant asp1 = new Aspirant(st1.Name, st1.Course, st1.GradeBook, "Hello world!");

      // 4. Вызвать метод Print() экземпляра asp1
      WriteLine("---------------------");
      WriteLine("The instance of asp1:");
      asp1.Print();
    }
  }
}

 



1.3. Результат работы программы
The instance of st1:
The values of fields are:
Name = Ivanov I.I.
Course = 2
GradeBook = 0519
---------------------
The instance of asp1:
The values of fields are:
Name = Ivanov I.I.
Course = 2
GradeBook = 0519
Topic = Hello world!

 

2. Реализация наследования на примере класса Book

2.1. Условие задачи

Задан класс Book, который описывает книгу. Класс содержит следующие элементы:

  • название книги;
  • фамилия и имя автора;
  • стоимость книги.

В классе Book нужно реализовать следующие методы:

  • конструктор с 3 параметрами;
  • свойства get/set для доступа к полям класса;
  • метод Print(), который выводит информацию о книге.

Разработать класс BookGenre, который наследует возможности класса Book и добавляет поле жанра (genre). В классе BookGenre реализовать следующие элементы:

  • конструктор с 4 параметрами – реализует вызов конструктора базового класса;
  • свойство get/set доступа к внутреннему полю класса;
  • метод Print(), который обращается к методу Print() базового класса Book для вывода информации о всех полях класса.

Разработать класс BookGenrePubl, который унаследован от класса BookGenre. Данный класс добавляет поле, которое содержит информацию об издателе. В классе BookGenrePubl реализовать следующие элементы:

  • конструктор с 5 параметрами;
  • свойство get/set для доступа к внутреннему полю класса;
  • метод Print(), который вызывает одноименный метод базового класса и выводит на экран информацию об издателе.

Класс BookGenrePubl сделать таким, что не может быть унаследован.

 

2.2. Решение. Текст программы
using static System.Console;

namespace ConsoleApp1
{
  // Класс Book - базовый класс
  class Book
  {
    // 1. Внутренние поля класса
    string title; // название (заголовок) книги
    string author; // фамилия и имя автора
    double price; // стоимость книги

    // 2. Конструктор с 3 параметрами
    public Book(string _title, string _author, double _price)
    {
      title = _title;
      author = _author;

      // корректировка стоимости книги
      if (price < 0) price = 0.0;
      else price = _price;
    }

    // 3. Свойства типа get/set для доступа к полям класса
    public string Title
    {
      get { return title; }
      set { title = value; }
    }

    public string Author
    {
      get { return author; }
      set { author = value; }
    }

    public double Price
    {
      get { return price; }
      set
      {
        if (price < 0) price = 0.0;
        else price = value;
      }
    }

    // 4. Метод Print() - вывести поля класса
    public void Print()
    {
      WriteLine("title = {0}, author = {1}, price = {2:f2}", title, author, price);
    }
  }

  // Класс, который наследует класс Book - добавляет жанр к книге.
  class BookGenre : Book
  {
    // 1. Внутреннее поле - жанр, к которому относится книга
    string genre;

    // 2. Конструктор с 4 параметрами.
    // Вызывает конструктор базового класса с помощью base(...).
    public BookGenre(string _title, string _author, double _price, string _genre) :
    base(_title, _author, _price)
    {
      genre = _genre;
    }

    // 3. Свойство доступа к полю genre
    public string Genre
    {
      get { return genre; }
      set { genre = value; }
    }

    // 4. Метод Print() - вызывает метод базового класса
    // В заголовке метода используется ключевое слово new. Это
    // есть рекомендация компилятора - подчеркнуть, что данный метод
    // прячет одноименный метод базового класса.
    public new void Print()
    {
      base.Print(); // вызвать метод Print() базового класса Book
      WriteLine("genre = {0}", genre);
    }
  }

  // Класс, который наследует класс BookGenre - добавляет к иерархии классов
  // поле издателя.
  // Перед классом используется ключевое слово sealed - это означает,
  // что данный класс не может быть унаследован другими классами.
  sealed class BookGenrePubl : BookGenre
  {
    // 1. Внутреннее поле - информация об издателе
    private string publisher;

    // 2. Конструктор с 5 параметрами - Вызывает конструктор базового
    // класса BookGenre() с помощью ключевого слова base.
    public BookGenrePubl(string _title, string _author, double _price,
        string _genre, string _publisher) : base(_title, _author, _price, _genre)
    {
      publisher = _publisher;
    }

    // 3. Свойство доступа к полю publisher
    public string Publisher
    {
      get { return publisher; }
      set { publisher = value; }
    }

    // 4. Метод Print() - вызывает метод базового класса.
    // В объявлении метода рекомендуется использовать
    // ключевое слово new, так как данный метод "прячет" метод базового класса.
    public new void Print()
    {
      base.Print();
      WriteLine("publisher = {0}", publisher);
    }
  }

  class Program
  {
    static void Main(string[] args)
    {
      // 1. Объявить экземпляр класса Book
      Book b1 = new Book("Title - 01", "Author - 01", 122.25);

      // 2. Вывести значения полей класса экземпляра b1
      b1.Print();

      // 3. Объявить экземпляр класса BookGenre
      BookGenre bg1 = new BookGenre("Title - BookGenre", "Author - BookGenre", 200.33, "Story");

      // 4. Вывести значения полей экземпляра bg1
      WriteLine("-------------------");
      bg1.Print();

      // 5. Объявить экземпляр класса BookGenrePubl
      BookGenrePubl bp1 = new BookGenrePubl("Title - BookGenrePubl", "Aurhor - BookGenrePubl",
          300.55, "Story", "Pupkin Inc.");

      // 6. Вывести значения полей экземпляра bp1
      WriteLine("-------------------");
      bp1.Print();
    }
  }
}

 

2.3. Результат работы программы
title = Title - 01, author = Author - 01, price = 122.25
-------------------
title = Title - BookGenre, author = Author - BookGenre, price = 200.33
genre = Story
-------------------
title = Title - BookGenrePubl, author = Aurhor - BookGenrePubl, price = 300.55
genre = Story
publisher = Pupkin Inc.

 


Связанные темы