SlideShare a Scribd company logo
Модуль 09 Наследование
1
2
Полиморфизм и переопределение
методов
3
 Обычное наследование всех членов
базового класса в классе-наследнике
 Переопределение членов базового
класса в классе-наследнике
 Скрытие членов базового класса в
классе-наследнике
4
Виртуальные методы, свойства и
индексаторы
5
Абстрактные классы
6
Класс Object
7
ToString()
GetHashCode()
Equals() и ReferenceEquals()
Finalize()
GetType()
Clone()
Методы System.Object
8
Класс object как универсальный тип
данных
9
Создание объектов
<тип класса> имя переменной = new <тип
класса>();
InfoUser myinfo = new InfoUser();
10
Типы значений и ссылочные типы
<тип класса> имя переменной = new <тип
класса>();
InfoUser myinfo = new InfoUser();

More Related Content

More from Yevgeniy Gertsen

модуль 17 основы xml
модуль 17 основы xmlмодуль 17 основы xml
модуль 17 основы xml
Yevgeniy Gertsen
 
модуль 16 взаимодействие с файловой системой
модуль 16 взаимодействие с файловой системоймодуль 16 взаимодействие с файловой системой
модуль 16 взаимодействие с файловой системой
Yevgeniy Gertsen
 
модуль 14 введение в generics
модуль 14 введение в genericsмодуль 14 введение в generics
модуль 14 введение в generics
Yevgeniy Gertsen
 
модуль 15 сборка мусора. рефлексия
модуль 15 сборка мусора. рефлексиямодуль 15 сборка мусора. рефлексия
модуль 15 сборка мусора. рефлексия
Yevgeniy Gertsen
 
модуль 13 использование коллекций
модуль 13 использование коллекциймодуль 13 использование коллекций
модуль 13 использование коллекций
Yevgeniy Gertsen
 
модуль 12 делегаты, события
модуль 12 делегаты, событиямодуль 12 делегаты, события
модуль 12 делегаты, события
Yevgeniy Gertsen
 
модуль 11 структуры, перечисления
модуль 11 структуры, перечислениямодуль 11 структуры, перечисления
модуль 11 структуры, перечисления
Yevgeniy Gertsen
 
Модуль 10 Интерфейсы
Модуль 10 ИнтерфейсыМодуль 10 Интерфейсы
Модуль 10 Интерфейсы
Yevgeniy Gertsen
 
Модуль 07 Перегрузка операторов
Модуль 07 Перегрузка операторовМодуль 07 Перегрузка операторов
Модуль 07 Перегрузка операторов
Yevgeniy Gertsen
 
модуль 06 пространства имен
модуль 06 пространства именмодуль 06 пространства имен
модуль 06 пространства имен
Yevgeniy Gertsen
 
модуль 05 обработка исключений
модуль 05 обработка исключениймодуль 05 обработка исключений
модуль 05 обработка исключений
Yevgeniy Gertsen
 
модуль 03 строки
модуль 03 строкимодуль 03 строки
модуль 03 строки
Yevgeniy Gertsen
 
модуль 03 массивы
модуль 03 массивымодуль 03 массивы
модуль 03 массивы
Yevgeniy Gertsen
 
модуль 02 основы языка программирования c#
модуль 02 основы языка программирования c#модуль 02 основы языка программирования c#
модуль 02 основы языка программирования c#
Yevgeniy Gertsen
 
модуль 01 введение в платформу microsoft .net
модуль 01 введение в платформу microsoft .netмодуль 01 введение в платформу microsoft .net
модуль 01 введение в платформу microsoft .net
Yevgeniy Gertsen
 

More from Yevgeniy Gertsen (18)

модуль 17 основы xml
модуль 17 основы xmlмодуль 17 основы xml
модуль 17 основы xml
 
модуль 16 взаимодействие с файловой системой
модуль 16 взаимодействие с файловой системоймодуль 16 взаимодействие с файловой системой
модуль 16 взаимодействие с файловой системой
 
модуль 14 введение в generics
модуль 14 введение в genericsмодуль 14 введение в generics
модуль 14 введение в generics
 
модуль 15 сборка мусора. рефлексия
модуль 15 сборка мусора. рефлексиямодуль 15 сборка мусора. рефлексия
модуль 15 сборка мусора. рефлексия
 
модуль 13 использование коллекций
модуль 13 использование коллекциймодуль 13 использование коллекций
модуль 13 использование коллекций
 
модуль 12 делегаты, события
модуль 12 делегаты, событиямодуль 12 делегаты, события
модуль 12 делегаты, события
 
модуль 11 структуры, перечисления
модуль 11 структуры, перечислениямодуль 11 структуры, перечисления
модуль 11 структуры, перечисления
 
Модуль 10 Интерфейсы
Модуль 10 ИнтерфейсыМодуль 10 Интерфейсы
Модуль 10 Интерфейсы
 
модуль 09-01
модуль 09-01модуль 09-01
модуль 09-01
 
модуль 08
модуль 08модуль 08
модуль 08
 
Модуль 07 Перегрузка операторов
Модуль 07 Перегрузка операторовМодуль 07 Перегрузка операторов
Модуль 07 Перегрузка операторов
 
модуль 06 пространства имен
модуль 06 пространства именмодуль 06 пространства имен
модуль 06 пространства имен
 
модуль 04
модуль 04модуль 04
модуль 04
 
модуль 05 обработка исключений
модуль 05 обработка исключениймодуль 05 обработка исключений
модуль 05 обработка исключений
 
модуль 03 строки
модуль 03 строкимодуль 03 строки
модуль 03 строки
 
модуль 03 массивы
модуль 03 массивымодуль 03 массивы
модуль 03 массивы
 
модуль 02 основы языка программирования c#
модуль 02 основы языка программирования c#модуль 02 основы языка программирования c#
модуль 02 основы языка программирования c#
 
модуль 01 введение в платформу microsoft .net
модуль 01 введение в платформу microsoft .netмодуль 01 введение в платформу microsoft .net
модуль 01 введение в платформу microsoft .net
 

модуль 09-02

Editor's Notes

  1. Наследование является одним из трех основополагающих принципов объектно-ориентированного программирования, поскольку оно допускает создание иерархических классификаций. Благодаря наследованию можно создать общий класс, в котором определяются характерные особенности, присущие множеству связанных элементов. От этого класса могут затем наследовать другие, более конкретные классы, добавляя в него свои индивидуальные особенности. В языке C# класс, который наследуется, называется базовым, а класс, который наследует, — производным. Следовательно, производный класс представляет собой специализированный вариант базового класса. Он наследует все переменные, методы, свойства и индексаторы, определяемые в базовом классе, добавляя к ним свои собственные элементы. Поддержка наследования в C# состоит в том, что в объявление одного класса разрешается вводить другой класс. Для этого при объявлении производного класса указывается базовый класс. При установке между классами отношения &amp;quot;является&amp;quot; строится зависимость между двумя или более типами классов. Базовая идея, лежащая в основе классического наследования, заключается в том, что новые классы могут создаваться с использованием существующих классов в качестве отправной точки Всякий раз, когда один класс наследует от другого, после имени производного класса указывается имя базового класса, отделяемое двоеточием. В C# синтаксис наследования класса удивительно прост и удобен в использовании.  Всегда помните, что наследование предохраняет инкапсуляцию, а потому приватные члены никогда не могут быть доступны через ссылку на объект. Т.е. поле inf из примера не может быть доступно для вызова с помощью экземпляра класса obj. Для любого производного класса можно указать только один базовый класс. В C# не предусмотрено наследование нескольких базовых классов в одном производном классе. (В этом отношении C# отличается от С++, где допускается наследование нескольких базовых классов. Данное обстоятельство следует принимать во внимание при переносе кода С++ в C#.) Тем не менее можно создать иерархию наследования, в которой производный класс становится базовым для другого производного класса. (Разумеется, ни один из классов не может быть базовым для самого себя как непосредственно, так и косвенно.) Но в любом случае производный класс наследует все члены своего базового класса, в том числе переменные экземпляра, методы, свойства и индексаторы. Главное преимущество наследования заключается в следующем: как только будет создан базовый класс, в котором определены общие для множества объектов атрибуты, он может быть использован для создания любого числа более конкретных производных классов. А в каждом производном классе может быть точно выстроена своя собственная классификация.
  2. Полиморфизм является третьим ключевым аспектом объектно-ориентированного программирования и предполагает способность к изменению функционала, унаследованного от базового класса. Полиморфизм предполагает определение полиморфного интерфейса в базовом классе - набор членов класса, которые могут быть переопределены в классе-наследнике. Методы, которые мы хотим сделать доступными для переопределения, в базовом классе помечается модификатором virtual. Такие методы называют виртуальными. Они и представляют полиморфный интерфейс (также частью полиморфного интерфейса могут быть абстрактные члены класса, о которых рассказывается в следующей теме). Переопределение метода – это изменение его реализации в классе наследнике. Переопределив метод, он будет работать по-разному в базовом классе и классе наследнике, имея при этом одно и то же имя и аргументы и тип возврата. https://metanit.com/sharp/tutorial/3.19.php http://mycsharp.ru/post/33/2013_10_19_virtualnye_metody_v_si-sharp_pereopredelenie_metodov.html
  3. При определении класса-наследника и наследовании методов базового класса мы можем выбрать одну из следующих стратегий
  4. http://www.intuit.ru/studies/courses/27/27/lecture/855%3Fpage%3D2 (пример виртуального класса) Полиморфизм предоставляет подклассу способ определения собственной версии метода, определенного в его базовом классе, с использованием процесса, который называется переопределением метода (method overriding). Чтобы пересмотреть текущий дизайн, нужно понять значение ключевых слов virtual и override. Виртуальным называется такой метод, который объявляется как virtual в базовом классе. Виртуальный метод отличается тем, что он может быть переопределен в одном или нескольких производных классах. Следовательно, у каждого производного класса может быть свой вариант виртуального метода. Кроме того, виртуальные методы интересны тем, что именно происходит при их вызове по ссылке на базовый класс. В этом случае средствами языка C# определяется именно тот вариант виртуального метода, который следует вызывать, исходя из типа объекта, к которому происходит обращение по ссылке, причем это делается во время выполнения. Поэтому при ссылке на разные типы объектов выполняются разные варианты виртуального метода. Иными словами, вариант выполняемого виртуального метода выбирается по типу объекта, а не по типу ссылки на этот объект. Так, если базовый класс содержит виртуальный метод и от него получены производные классы, то при обращении к разным типам объектов по ссылке на базовый класс выполняются разные варианты этого виртуального метода. Метод объявляется как виртуальный в базовом классе с помощью ключевого слова virtual, указываемого перед его именем. Когда же виртуальный метод переопределяется в производном классе, то для этого используется модификатор override. А сам процесс повторного определения виртуального метода в производном классе называется переопределением метода. При переопределении метода - имя, возвращаемый тип и сигнатура переопределяющего метода должны быть точно такими же, как и у того виртуального метода, который переопределяется. Кроме того, виртуальный метод не может быть объявлен как static или abstract. Переопределение метода служит основанием для воплощения одного из самых эффективных в C# принципов: динамической диспетчеризации методов, которая представляет собой механизм разрешения вызова во время выполнения, а не компиляции. Значение динамической диспетчеризации методов состоит в том, что именно благодаря ей в C# реализуется динамический полиморфизм. Если при наличии многоуровневой иерархии виртуальный метод не переопределяется в производном классе, то выполняется ближайший его вариант, обнаруживаемый вверх по иерархии. И еще одно замечание: свойства также подлежат модификации ключевым словом virtual и переопределению ключевым словом override. Это же относится и к индексаторам. https://professorweb.ru/my/csharp/charp_theory/level7/7_6.php
  5. Иногда требуется создать базовый класс, в котором определяется лишь самая общая форма для всех его производных классов, а наполнение ее деталями предоставляется каждому из этих классов. В таком классе определяется лишь характер методов, которые должны быть конкретно реализованы в производных классах, а не в самом базовом классе. Подобная ситуация возникает, например, в связи с невозможностью получить содержательную реализацию метода в базовом классе. Создавая собственные библиотеки классов, вы можете сами убедиться в том, что у метода зачастую отсутствует содержательное определение в контексте его базового класса. Подобная ситуация разрешается двумя способами. Один из них состоит в том, чтобы просто выдать предупреждающее сообщение. Такой способ может пригодиться в определенных ситуациях, например при отладке, но в практике программирования он обычно не применяется. В подобных случаях требуется какой-то способ, гарантирующий, что в производном классе действительно будут переопределены все необходимые методы. И такой способ в C# имеется. Он состоит в использовании абстрактного метода. Абстрактный метод создается с помощью указываемого модификатора типа abstract. У абстрактного метода отсутствует тело, и поэтому он не реализуется в базовом классе. Это означает, что он должен быть переопределен в производном классе, поскольку его вариант из базового класса просто непригоден для использования. Нетрудно догадаться, что абстрактный метод автоматически становится виртуальным и не требует указания модификатора virtual. В действительности совместное использование модификаторов virtual и abstract считается ошибкой. Для определения абстрактного метода служит приведенная ниже общая форма: abstract тип имя(список_параметров); Как видите, у абстрактного метода отсутствует тело. Модификатор abstract может применяться только в методах экземпляра, но не в статических методах (static). Абстрактными могут быть также индексаторы и свойства. Класс, содержащий один или больше абстрактных методов, должен быть также объявлен как абстрактный, и для этого перед его объявлением class указывается модификатор abstract. А поскольку реализация абстрактного класса не определяется полностью, то у него не может быть объектов. Следовательно, попытка создать объект абстрактного класса с помощью оператора new приведет к ошибке во время компиляции! Когда производный класс наследует абстрактный класс, в нем должны быть реализованы все абстрактные методы базового класса. В противном случае производный класс должен быть также определен как abstract. Таким образом, атрибут abstract наследуется до тех пор, пока не будет достигнута полная реализация класса.
  6. В C# предусмотрен специальный класс object, который неявно считается базовым классом для всех остальных классов и типов, включая и типы значений. Иными словами, все остальные типы являются производными от object. Это, в частности, означает, что переменная ссылочного типа object может ссылаться на объект любого другого типа. Кроме того, переменная типа object может ссылаться на любой массив, поскольку в C# массивы реализуются как объекты. Формально имя object считается в C# еще одним обозначением класса System.Object, входящего в библиотеку классов для среды .NET Framework. Практическое значение этого в том, что помимо методов и свойств, которые вы определяете, также появляется доступ к множеству общедоступных и защищенных методов-членов, которые определены в классе Object. Эти методы присутствуют во всех определяемых классах. Примеры утут https://professorweb.ru/my/csharp/charp_theory/level5/5_2.php
  7. ToString() Метод ToString() возвращает символьную строку, содержащую описание того объекта, для которого он вызывается. Кроме того, метод ToString() автоматически вызывается при выводе содержимого объекта с помощью метода WriteLine(). Этот метод переопределяется во многих классах, что позволяет приспосабливать описание к конкретным типам объектов, создаваемых в этих классах. Применяйте этот метод, когда нужно получить представление о содержимом объекта — возможно, в целях отладки. Он предлагает очень ограниченные средства форматирования данных. Например, даты в принципе могут быть отображены в огромном разнообразии форматов, но DateTime.ToString() не оставляет никакого выбора в этом отношении. Если нужно более сложное строковое представление, которое, например, принимает во внимание установленные предпочтения или местные стандарты, то понадобится реализовать интерфейс IFormattable. GetHashCode() Этот метод используется, когда объект помещается в структуру данных, известную как карта (map), которая также называется хеш-таблицей или словарем. Применяется классами, которые манипулируют этими структурами, чтобы определить, куда именно в структуру должен быть помещен объект. Если вы намерены использовать свой класс как ключ словаря, то должны переопределить GetHashCode(). Существуют достаточно строгие требования относительно того, как нужно реализовывать перегрузку. Хеш-код можно использовать в любом алгоритме, где хеширование применяется в качестве средства доступа к хранимым объектам. Следует, однако, иметь в виду, что стандартная реализация метода GetHashCode() не пригодна на все случаи применения. Equals() и ReferenceEquals() По умолчанию метод Equals (object) определяет, ссылается ли вызывающий объект на тот же самый объект, что и объект, указываемый в качестве аргумента этого метода, т.е. он определяет, являются ли обе ссылки одинаковыми. Метод Equals (object) возвращает логическое значение true, если сравниваемые объекты одинаковы, в противном случае — логическое значение false. Он может быть также переопределен в создаваемых классах. Это позволяет выяснить, что же означает равенство объектов для создаваемого класса. Например, метод Equals (object) можно определить таким образом, чтобы в нем сравнивалось содержимое двух объектов. Как несложно догадаться, учитывая существование трех различных методов сравнения объектов, среда .NET использует довольно сложную схему определения эквивалентности объектов. Следует учитывать и использовать тонкие различия между этими тремя методами и операцией сравнения ==. Кроме того, также существуют ограничения, регламентирующие, как следует переопределять виртуальную версию Equals() с одним параметром, если вы решитесь на это — поскольку некоторые базовые классы из пространства имен System.Collections вызывают этот метод и ожидают от него определенного поведения. Finalize() Назначение этого метода в C# примерно соответствует деструкторам С++, и он вызывается при сборке мусора для очистки ресурсов, занятых ссылочным объектом. Реализация Finalize() из Object на самом деле ничего не делает и игнорируется сборщиком мусора. Обычно переопределять Finalize() необходимо, если объект владеет неуправляемыми ресурсами, которые нужно освободить при его уничтожении. Сборщик мусора не может сделать это напрямую, потому что он знает только об управляемых ресурсах, поэтому полагается на финализацию, определенную вами. GetType() Этот метод возвращает экземпляр класса, унаследованный от System.Type. Этот объект может предоставить большой объем информации о классе, членом которого является ваш объект, включая базовый тип, методы, свойства и т.п. System.Type также представляет собой стартовую точку технологии рефлексии .NET. Clone() Этот метод создает копию объекта и возвращает ссылку на эту копию (а в случае типа значения — ссылку на упаковку). Отметим, что при этом выполняется неглубокое копирование, т.е. копируются все типы значений в классе. Если же класс включает в себя члены ссылочных типов, то копируются только ссылки, а не объекты, на которые они указывают. Этот метод является защищенным, а потому не может вызываться для копирования внешних объектов. К тому же он не виртуальный, а потому переопределять его реализацию нельзя.
  8. Если object является базовым классом для всех остальных типов и упаковка значений простых типов происходит автоматически, то класс object можно вполне использовать в качестве &amp;quot;универсального&amp;quot; типа данных. Для примера рассмотрим программу, в которой сначала создается массив типа object, элементам которого затем присваиваются значения различных типов данных по ссылке на объект класса object можно обращаться к данным любого типа, поскольку в переменной ссылочного типа object допускается хранить ссылку на данные всех остальных типов. Следовательно, в массиве типа object из рассматриваемого здесь примера можно сохранить данные практически любого типа. В развитие этой идеи можно было бы, например, без особого труда создать класс стека со ссылками на объекты класса object. Это позволило бы хранить в стеке данные любого типа. Несмотря на то что универсальный характер класса object может быть довольно эффективно использован в некоторых ситуациях, было бы ошибкой думать, что с помощью этого класса стоит пытаться обойти строго соблюдаемый в C# контроль типов. Вообще говоря, целое значение следует хранить в переменной типа int, строку — в переменной ссылочного типа string и т.д. А самое главное, что начиная с версии 2.0 для программирования на C# стали доступными подлинно обобщенные типы данных — обобщения. Внедрение обобщений позволило без труда определять классы и алгоритмы, автоматически обрабатывающие данные разных типов, соблюдая типовую безопасность. Благодаря обобщениям отпала необходимость пользоваться классом object как универсальным типом данных при создании нового кода. Универсальный характер этого класса лучше теперь оставить для применения в особых случаях.
  9. Эта строка объявления выполняет три функции. Во-первых, объявляется переменная myinfo, относящаяся к типу класса InfoUser. Сама эта переменная не является объектом, а лишь переменной, которая может ссылаться на объект. Во-вторых, создается конкретная, физическая, копия объекта. Это делается с помощью оператора new. И наконец, переменной myinfo присваивается ссылка на данный объект. Таким образом, после выполнения анализируемой строки объявленная переменная myinfo ссылается на объект типа InfoUser. Оператор new динамически (т.е. во время выполнения) распределяет память для объекта и возвращает ссылку на него, которая затем сохраняется в переменной. Следовательно, в C# для объектов всех классов должна быть динамически распределена память. То обстоятельство, что объекты классов доступны по ссылке, объясняет, почему классы называются ссылочными типами. Главное отличие типов значений от ссылочных типов заключается в том, что именно содержит переменная каждого из этих типов. Так, переменная типа значения содержит конкретное значение, а ссылочная переменная содержит не сам объект, а лишь ссылку на него.
  10. https://metanit.com/sharp/tutorial/2.16.php Типы значений: Целочисленные типы (byte, sbyte, char, short, ushort, int, uint, long, ulong) Типы с плавающей запятой (float, double) Тип decimal Тип bool Перечисления enum Структуры (struct) Ссылочные типы: Тип object Тип string Классы (class) Интерфейсы (interface) Делегаты (delegate) В чем же между ними различия? Для этого надо понять организацию памяти в .NET. Здесь память делится на два типа: стек и куча (heap). Все типы значений являются производными от типа System.ValueType и размещают свое значение в стеке. Стек представляет собой структуру данных, которая растет снизу вверх: каждый новый добавляемый элемент помещаются поверх предыдущего. Время жизни переменных таких типов ограничено их контекстом. Физически стек - это некоторая область памяти в адресном пространстве. Когда программа только запускается на выполнение, в конце блока памяти, зарезервированного для стека устанавливается указатель стека. При помещении данных в стек указатель переустанавливается таким образом, что снова указывает на новое свободное место.