C# наследование метода

Конструкторы и наследование

В иерархии классов допускается, чтобы у базовых и производных классов были свои собственные конструкторы. В связи с этим возникает следующий резонный вопрос: какой конструктор отвечает за построение объекта производного класса: конструктор базового класса, конструктор производного класса или же оба? На этот вопрос можно ответить так: конструктор базового класса конструирует базовую часть объекта, а конструктор производного класса — производную часть этого объекта. И в этом есть своя логика, поскольку базовому классу неизвестны и недоступны любые элементы производного класса, а значит, их конструирование должно происходить раздельно.

Если конструктор определен только в производном классе, то все происходит очень просто: конструируется объект производного класса, а базовая часть объекта автоматически собирается его конструктором, используемым по умолчанию.

Когда конструкторы определяются как в базовом, так и в производном классе, процесс построения объекта несколько усложняется, поскольку должны выполняться конструкторы обоих классов. В данном случае приходится обращаться к ключевому слову base, которое находит двоякое применение: во-первых, для вызова конструктора базового класса; и во-вторых, для доступа к члену базового класса, скрывающегося за членом производного класса.

С помощью формы расширенного объявления конструктора производного класса и ключевого слова base в производном классе может быть вызван конструктор, определенный в его базовом классе. Ниже приведена общая форма этого расширенного объявления:

где список_аргументов обозначает любые аргументы, необходимые конструктору в базовом классе. Обратите внимание на местоположение двоеточия.

Давайте рассмотрим пример:

С помощью ключевого слова base можно вызвать конструктор любой формы, определяемой в базовом классе, причем выполняться будет лишь тот конструктор, параметры которого соответствуют переданным аргументам.

А теперь рассмотрим вкратце основные принципы действия ключевого слова base. Когда в производном классе указывается ключевое слово base, вызывается конструктор из его непосредственного базового класса. Следовательно, ключевое слово base всегда обращается к базовому классу, стоящему в иерархии непосредственно над вызывающим классом. Это справедливо даже для многоуровневой иерархии классов. Аргументы передаются базовому конструктору в качестве аргументов метода base(). Если же ключевое слово отсутствует, то автоматически вызывается конструктор, используемый в базовом классе по умолчанию.

Основы наследования

Наследование является одним из трех основополагающих принципов объектно-ориентированного программирования, поскольку оно допускает создание иерархических классификаций. Благодаря наследованию можно создать общий класс, в котором определяются характерные особенности, присущие множеству связанных элементов. От этого класса могут затем наследовать другие, более конкретные классы, добавляя в него свои индивидуальные особенности.

В языке C# класс, который наследуется, называется базовым, а класс, который наследует, — производным. Следовательно, производный класс представляет собой специализированный вариант базового класса. Он наследует все переменные, методы, свойства и индексаторы, определяемые в базовом классе, добавляя к ним свои собственные элементы.

Поддержка наследования в C# состоит в том, что в объявление одного класса разрешается вводить другой класс. Для этого при объявлении производного класса указывается базовый класс. При установке между классами отношения «является» строится зависимость между двумя или более типами классов. Базовая идея, лежащая в основе классического наследования, заключается в том, что новые классы могут создаваться с использованием существующих классов в качестве отправной точки:

Всякий раз, когда один класс наследует от другого, после имени производного класса указывается имя базового класса, отделяемое двоеточием. В C# синтаксис наследования класса удивительно прост и удобен в использовании. Ниже представлено схематичное представление класса CSharp из вышеуказанного примера:

Как видите класс CSharp получает доступ к полям и методам класса ProfessorWeb. Всегда помните, что наследование предохраняет инкапсуляцию, а потому приватные члены никогда не могут быть доступны через ссылку на объект. Т.е. поле inf из примера не может быть доступно для вызова с помощью экземпляра класса obj.

Для любого производного класса можно указать только один базовый класс. В C# не предусмотрено наследование нескольких базовых классов в одном производном классе. (В этом отношении C# отличается от С++, где допускается наследование нескольких базовых классов. Данное обстоятельство следует принимать во внимание при переносе кода С++ в C#.) Тем не менее можно создать иерархию наследования, в которой производный класс становится базовым для другого производного класса. (Разумеется, ни один из классов не может быть базовым для самого себя как непосредственно, так и косвенно.) Но в любом случае производный класс наследует все члены своего базового класса, в том числе переменные экземпляра, методы, свойства и индексаторы.

Главное преимущество наследования заключается в следующем: как только будет создан базовый класс, в котором определены общие для множества объектов атрибуты, он может быть использован для создания любого числа более конкретных производных классов. А в каждом производном классе может быть точно выстроена своя собственная классификация.

Наследование в C#

Всем доброго времени суток. На связи Алексей Гулынин. В прошлой статье вы узнали немного о том, что такое делегаты в C#. В данной статье я бы хотел рассказать про наследование в C#. Простыми словами, «Наследование» означает то, что мы создаём класс на основе другого. Получается, у нас есть родительский класс и дочерний класс, который наследует все поля и методы родительского класса. Для того, чтобы понять, что такое наследование и для чего его нужно использовать, вернёмся к понятию объекта.

Объект представляет собой некую абстрактную сущность. Допустим мы хотим создать класс «Animal» (Животное). Но животных же существует великое множество и вряд ли мы одним классом сможем описать их всех. В классе «Animal» мы можем создать поля и методы, присущие всем животным. Например, полями общими для всех животных могут быть «Вес», «Средняя продолжительность жизни», «Имеется хвост или нет». Методом может быть «eat()» (кушать), ведь все же животные питаются. От такого общего класса мы можем создать дочерний класс, который расширяет родительский класс. Например, класс «Dog» (собака) может расширять класс «Animal» уже конкретными полями и методами, которые соответствуют именно собакам.

Отношение наследования — это отношение перехода от более общей абстракции к более конкретной.

В C# наследование является одиночным, то есть нельзя наследоваться от двух и более классов. Наследование определяется через «:».

Интересный момент: если вы пишете обычный класс, который не имеет родителя, то, по умолчанию, этот класс является наследником класса «Object». Класс «Object» является родителем абсолютно для всех классов в .NET.

Немного поговорим про понятия, так или иначе связанные с наследованием.

Абстрактный класс — это класс, объекты которого нельзя создавать, т.е. нельзя будет использовать ключевое слово «new». Абстрактные классы используются при наследовании и используются как прародители к другим классам (реальным, не абстрактным). Т.е. в нашем примере можно класс «Animal» пометить как «abstract». Абстрактным может быть также и метод (это метод без реализации). Если в классе присутствует хотя бы один абстрактный метод, то и сам класс обязан быть абстрактным. В обратную сторону правило не действует.

С помощью ключевого слова «sealed» можно запретить создавать наследников от класса. Пример: класс «String». От этого класса мы не сможем создать наследников. Применение ключевого слова «sealed» к методу означает, что мы запрещаем переопределение этого метода в классах-наследниках.

Ключевое слово «virtual» применяется только к методам, и используется для того, чтобы превратить метод в виртуальный. Это делается для того, чтобы метод можно было переопределить в классах-наследниках. Переопределение метода означает, что мы внутри класса-наследника создаём метод, у которого заголовок полностью совпадает с заголовком метода класса-родителя. При этом в классе-наследнике нужно указать ключевое слово «override», чтобы явно указать, что мы переопределяем метод.

Давайте на примере разберем всё то, что мы только что узнали. Для простоты все поля и методы сделаем публичными (в реальных программах так, конечно, делать не нужно):

Конструкторы при наследовании.

Конструкторы не наследуются. Если в родительском классе определены различные конструкторы, то при наследовании эти конструкторы будут недоступны у класса-наследника. Несмотря на то, что конструкторы не наследуются — они автоматически вызываются. Когда вызывается конструктор класса-наследника автоматом вызывается конструктор класса-родителя. По умолчанию будет вызываться дефолтный конструктор класса-наследника без параметров. Обращаю ваше внимание на то, что если такого конструктора без параметров не будет, то будет получена ошибка при компиляции.

Если мы хотим, чтобы вызывался другой родительский конструктор, то это можно указать с помощью ключевого слова «base» .

С помощью «base» также можно вызывать родительский метод.

Разберем на эту тему вот такой пример: пусть имеется родительский класс «Degree», имеющий одной поле «degrees» и один метод, который возвращает значение данного поля. Создадим дочерний класс «Radiance», который, используя метод родительского класса, возвращает градусы, переведенные в радианы:

Напоследок, обобщу особенности наследования:

  • Ключевые слова «sealed» и «static» (статический класс, про него поговорим в отдельной статье) запрещают наследование
  • Если в базовом классе определен какой-то метод «abstract», то базовый класс тоже должен быть абстрактным. В классе-наследнике такой абстрактный метод нужно переопределить. Абстрактный метод, по умолчанию, является виртуальным.
  • При проектировании программы важным является понимание того, что от чего можно унаследовать, а что нельзя. Для проверки условия наследования используется слово «является». В нашем примере: «Собака является животным? — является», «Питбуль является собакой? — является». А вот наоборот лучше не делать (технически конечно можно, но программы лучше сразу проектировать правильно), «Животное является собакой? — не является». Поэтому класс «Animal» от класса «Dog» наследовать нельзя.

В данной статье вы узнали про механизм наследования в C# и о том, как его лучше использовать.

На связи был Алексей Гулынин, оставляйте свои комментарии, увидимся в следующих статьях.

C# наследование метода

Рассмотрим основные принципы наследование классов в C#.

Вспомним из предыдущей статьи синтаксис класса:

[атрибуты]
[модификаторы] class Имя_класса : [родитель]
<
>
Под родителем понимается класс, от которого наследуется данный. Существует несколько понятий, имеющих одно и то же значение, обозначающие наследуемый класс — базовый класс (base class) , родительский класс (parent class), предок. Класс, который наследует, называется производным, потомком или наследником. Потомок наследует все поля, свойства, методы, индексаторы, операторы от предка, помеченные соответствующим модификатором доступа. Кроме этого он может иметь собственные элементы или переопределить существующие.
Наследование можно рассмотреть на примере класса Point2D и класса Point3D, который от него наследуется.

class Point2D
<
protected double x; // поле доступно только в производных классах
protected double y; // поле доступно только в производных классах
public Point2D(double x, double y)
<
this.x = x;
this.y = y;
>
protected Point2D()
:this(0,0)
< >
>

class Point3D : Point2D
<
private double z;
Point3D(double x, double y, double z)
:base(x,y)
<
this.z = z;
>
>

В данном случае класс Point3D наследует переменные x, y, а также конструктор базового класса. Параметр base действует аналогично this, только используется он всегда для доступа к членам класса-предка, в то время как this — ссылается на текущий экземпляр класса. В этом случае часть объекта, соответствующая базовому классу, создается через вызов его конструктора. А часть, соответствующая производному, — с помощью конструктора потомка. Через параметр base можно вызвать любой конструктор базового класса с соответствующими параметрами.
Добавим по методу GetRadius() в оба класса:

// в Point2D
public double GetRadius()
<
return Math.Sqrt(x * x + y * y);
>
// в Point3D
public new double GetRadius()
<
return Math.Sqrt(x * x + y * y + z * z);
>

Это называется перекрытием метода, а точнее скрытием. В данном случае модификатор new явно скрывает базовый метод GetRadius() и заменяет его методом в производном классе.
Класс, помеченный модификатором sealed не может быть унаследован.

0. В «синтаксисе класса» навскидку пропущено два пункта. Если пропустили сознательно — почему бы не написать «в упрощенном синтаксисе класса» или что-то вроде этого?

1. В предыдущей статье ошибка — у класса может быть только один родитель.

2. Зачем?
protected Point2D()
:this(0,0)

3. protected double x; // поле доступно только в производных классах
В комментарии оговорка, еще и в объекте этого класса.

4. В данном случае класс Point3D наследует переменные x, y, а также конструктор базового класса
Point3D наследует конструктор базового класса? Почему же пример ниже не работает? ?
Point3D point = new Point3D (3, 4);

5. Последний пример (с сокрытием метода) явно вредный. Люди потом удивляются, почему же код вроде этого работает через ..опу?

Point2D point = new Point3D(3, 4, 5);
Console.WriteLine(point.GetRadius);

6. Про всякие «оговорки» вроде «this ссылается на этот класс» (к которым придираются на собеседованиях/экзаменах) даже говорить не буду.

Вот честное слово, так люблю читать твои комментарии. Они всегда конструктивные. Автор статьи в ближайшее время ответит на них.

0. Как угодно, «упрощенный синтаксис». Тут цель — просто показать запись класса-предка в объявлении.
1. Конечно, исправил.
2. Если честно, не понял вопроса. Не нравится, что нулевые значения передаются?
3. Согласен.
4. Я фигню написал.) Конструкторы классов наследников вызывают конструкторы класса-предка, например, непараметризованный конструктрор Point3D() будет вызывать Point2D(). Мы можем только явно указать, какой из конструкторов будет вызываться.
5. Ну я не написал, что это приветствуется. Просто надо знать, что такая вещь есть.
6. Ссылается на текущий экземпляр класса.

Спасибо Вам за обучающую информацию. Очень много полезного для начинающих. Есть пара вопросов:
1. Будет ли продолжение статей по С#?
2. Есть ли у Вас какой-нибудь сборник задач по программированию? Для разных уровней мастерства)
А в остальном еще раз спасибо за сайт)

C# наследование метода

ZORK>Более конкретно смотри раздел 10.5.5 в C# спецификации

Пардон, я та глубоко не рыл. Смотрел по книге Э. Руннерсона «Введение в C#» (она есть в RSDN
Ресурсы/Книги/.Net). Там говорится о sealed только для классов. На будущее буду знать.

Здравствуйте Mishka, Вы писали:

M>Всем спасибо! Действительно работает.

Слушай, а зачем тебе нужно помечать виртуальный метод как saled? Я просто немогу себе представить такой ситуации. 🙁

Здравствуйте VladD2, Вы писали:

VD>Здравствуйте Mishka, Вы писали:

M>>Всем спасибо! Действительно работает.

VD>Слушай, а зачем тебе нужно помечать виртуальный метод как saled? Я просто немогу себе представить такой ситуации. 🙁

Ну такие потребности настпают, когда работаешь с многоуровневым коллекитивом программистов, или просто делаешь библиотеку классов для третей компании. Тогда, может оказаться что тебе надо виртуальный метод, для того чтобы исползьзвать полиморфизм в своей библиотек, но с другой стороны, может быть важно что-бы пользователи этой библиотеки не могли так просто изменить поведение базовых классов — так как при их неосведомленость о дизайне библиотеки, ни до чего хорошего не доведет.

С этим очевидно можно спорить, но например в американском контрактно программировнии я нашел важным иметь возиможность защитить свои классы и код в целом на уровне дизайна. Например: не дать возможно сломать твои классы, простым наследованием и писанием всякой ерунды — от непонимания.

Это интересно:

  • Правило одна и две буквы н в суффиксах причастий Азбучные истины Интерактивный диктант Учебник ГРАМОТЫ: орфография Учебник ГРАМОТЫ: пунктуация Имена и названия. Интерактивный тренажер Полезные ссылки Летнее чтение Запоминалки Цитаты о языке Скороговорки Пословицы и поговорки Учебник ГРАМОТЫ: орфография Выберите правильные варианты […]
  • Возврат страховки в атб Отзывы о потребительских кредитах Азиатско-Тихоокеанского Банка 01.08.2018 обратилась в ОО №80 г Хабаровск для оформления Потребительского кредита на сумму 300 000= рублей. На момент документального оформления в офисе находилась одна сотрудница менеджер К-ская Ю.И. которая со мной и […]
  • Ст 188 ук рф ч2 Ст 188 ук рф ч2 1. Контрабанда посягает на монополию внешней торговли государства со всеми вытекающими отсюда негативными последствиями для экономики Российской Федерации.2. Контрабанда заключается в незаконном перемещении через таможенную границу РФ товаров или иных предметов.3. […]
  • Закон утратил юридическую силу это Действие нормативных актов Юридическая техника Предмет и методы юридической техники Понятие и виды юридической техники Структура юридической техники Средства и приемы юридической техники Правовая семья Юридические документы: понятие и виды Профессия юриста Действие […]
  • Выписка из егрюл в мировой суд Выписка из егрюл в мировой суд Дело № 5-1386/2013 года 13 марта 2013 года г. Омск Исполняющий обязанности мирового судьи судебного участка № 106 Кировского АО города Омска, мировой судья судебного участка № 50 КАО г. Омска Смирнова Г.А. (Омск, ул. Седова,57/1), рассмотрев в открытом […]
  • Федеральный закон статья 231 Статья 231. УК РФ Незаконное культивирование растений, содержащих наркотические средства или психотропные вещества либо их прекурсоры 1. Незаконное культивирование в крупном размере растений, содержащих наркотические средства или психотропные вещества либо их прекурсоры, - наказывается […]
  • Ст 131 п 2 ук рф АДВОКАТСКИЕ ТАЙНЫ Адвокатские тайны ౹ Алексей Колегов ౹ Адвокат Колегов Статья 131 УК РФ — изнасилование Это самое опасное и наиболее распространенное из половых преступлений. Согласно ч. 1 ст. 131 УК, изнасилование – это половое сношение с применением насилия или с угрозой его […]
  • Заявления на алименты 25 процентов Исковое заявление об уменьшении размера алиментов Очень часто исковое заявление об уменьшении размера алиментов связывается исключительно с рождением еще одного ребенка. Ситуация распространенная: родитель вступает в новый брак, где рождается ребенок, и просит о снижении размера […]

Author: admin