Лекция 9. Наследование

Наследование (inheritance) является одним из ключевых моментов ООП. Его смысл состоит в том, что мы можем расширить функциональность уже существующих классов за счет добавления нового функционала или изменения старого. Пусть у нас есть следующий класс Person, описывающий отдельного человека:

class Person

{

           private string _firstName;

private string _lastName;

               

public string FirstName

           {

                          get { return _firstName; }

   set { _firstName = value; }

           }

public string LastName

           {

                          get { return _lastName; }

   set { _lastName = value; }

           }

 

public void Display()

{

   Console.WriteLine(FirstName + " " + LastName);

}

}

Но вдруг нам потребовался класс, описывающий сотрудника предприятия - класс Employee. Поскольку этот класс будет реализовывать тот же функционал, что и класс Person, так как сотрудник - это также и человек, то было бы рационально сделать класс Employee производным (или наследником, или подклассом) от класса Person, который, в свою очередь, называется базовым классом или родителем (или суперклассом):

class Employee: Person

{

               

}

После двоеточия мы указываем базовый класс для данного класса. Для класса Employee базовым является Person, и поэтому класс Employee наследует все те же свойства, методы, поля, которые есть в классе Person. Единственное, что не передается при наследовании, это конструкторы базового класса.

Таким образом, наследование реализует отношение is-a (является), объект класса Employee также является объектом класса Person:

static void Main(string[] args)

{

           Person p = new Person { FirstName = "Bill", LastName = "Gates" };

           p.Display();

           p = new Employee { FirstName = "Denis", LastName = "Ritchi" };

           p.Display();

           Console.Read();

}

И поскольку объект Employee является также и объектом Person, то мы можем так определить переменную: Person p = new Employee().

Все классы по умолчанию могут наследоваться. Однако здесь есть ряд ограничений:

· Не поддерживается множественное наследование, класс может наследоваться только от одного класса. Хотя проблема множественного наследования реализуется с помощью концепции интерфейсов, о которых мы поговорим позже.

· При создании производного класса надо учитывать тип доступа к базовому классу - тип доступа к производному классу должен быть таким же, как и у базового класса, или более строгим. То есть, если базовый класс у нас имеет тип доступа internal, то производный класс может иметь тип доступа internal или private, но не public.

· Если класс объявлен с модификатором sealed, то от этого класса нельзя наследовать и создавать производные классы.

Например, следующий класс не допускает создание наследников:

sealed class Admin

{

}

Доступ к членам базового класса из класса-наследника

Вернемся к нашим классам Person и Employee. Хотя Employee наследует весь функционал от класса Person, посмотрим, что будет в следующем случае:

class Employee: Person

{

public void Display()

{

   Console.WriteLine(_firstName);

}

}

Этот код не сработает и выдаст ошибку, так как переменная _firstName объявлена с модификатором private и поэтому к ней доступ имеет только класс Person. Но зато в классе Person определено общедоступное свойство FirstName, которое мы можем использовать, поэтому следующий код у нас будет работать нормально:

class Employee: Person

{

public void Display()

{

   Console.WriteLine(FirstName);

}

}

Таким образом, производный класс может иметь доступ только к тем членам базового класса, которые определены с модификаторамиpublic, internal, protected и protected internal.

Ключевое слово base

Теперь добавим в наши классы конструкторы:

class Person

{

public string FirstName { get; set; }

public string LastName {get; set; }

 

public Person(string fName, string lName)

{

   FirstName = fName;

   LastName = lName;

}

 

public void Display()

{

   Console.WriteLine(FirstName + " " + LastName);

}

}

 

class Employee: Person

{

public string Company { get; set; }

 

public Employee(string fName, string lName, string comp)

                                         :base(fName, lName)

{

   Company = comp;

}

}

Класс Person имеет стандартный конструктор, который устанавливает два свойства. Поскольку класс Employee наследует и устанавливает те же свойства, что и класс Person, то логично было бы не писать по сто раз код установки, а как-то вызвать соответствующий код класса Person. К тому же свойств, которые надо установить, и параметров может быть гораздо больше.

С помощью ключевого слова base мы можем обратиться к базовому классу. В нашем случае в конструкторе класса Employee нам надо установить имя, фамилию и компанию. Но имя и фамилию мы передаем на установку в конструктор базового класса, то есть в конструктор класса Person, с помощью выражения base(fName, lName).

static void Main(string[] args)

{

           Person p = new Person("Bill", "Gates");

p.Display();

Employee emp = new Employee ("Tom", "Simpson", "Microsoft");

emp.Display();

           Console.Read();

}


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: