C#. Примеры создания иерархий классов с использованием наследования
В данной теме рассматривается два примера разработки классов с использованием наследования. Каждый пример содержит комментарии с объяснениями особенностей работы соответствующего фрагмента кода. При создании иерархий классов полиморфизм не используется.
Тема будет полезна начинающим программистам при изучении основ программирования классов, использующих наследование.
Содержание
- 1. Пример создания иерархии классов. Классы Student, Aspirant
- 2. Реализация наследования на примере класса Book
- Связанные темы
Поиск на других ресурсах:
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.
⇑
Связанные темы
- Наследование. Базовые понятия. Преимущества и недостатки. Общая форма. Простейшие примеры. Модификатор доступа protected
- Использование конструкторов в классах при наследовании. Ключевое слово base при наследовании
- Доступ к элементам базового класса из унаследованного класса. Ключевые слова base, new. Примеры
⇑