C# - Главная Пространство имен
► System ► Microsoft Для учеников (начинающих)
► Видео уроки ► Обучение ► Примеры программ ► Секреты в Си Шарп Для профессионалов
► Обучение ► Примеры программ ► Задачки - для тебя! |
НаследованиеНаследование — один из трех фундаментальных принципов объектно-ориентированного программирования, поскольку именно благодаря ему возможно создание иерархических классификаций. Используя наследование, можно создать общий класс, который определяет характеристики, присущие множеству связанных элементов. Этот класс затем может быть унаследован другими, узкоспециализированными классами с добавлением в каждый из них своих, уникальных особенностей. В языке С# класс, который наследуется, называется базовым. Класс, который наследует базовый класс, называется производным. Следовательно, производный класс — это специализированная версия базового класса. В производный класс, наследующий все переменные, методы, свойства, операторы и индексаторы, определенные в базовом классе, могут быть добавлены уникальные элементы. С# поддерживает наследование, позволяя в объявление класса встраивать другой класс. Это реализуется посредством задания базового класса при объявлении производного. Лучше всего начать с примера. Рассмотрим класс TwoDShape, в котором определяются атрибуты "обобщенной" двумерной геометрической фигуры {например, квадрата, прямоугольника, треугольника и т.д.).
// Класс двумерных объектов, class TwoDShape { public double width; public double height; public void showDiraO { Console.WriteLine("Ширина и высота равны " + width + " и " + height); ) }
Класс TwoDShape можно использовать в качестве базового (т.е. как стартовую площадку) для классов, которые описывают специфические типы двумерных объектов. Например, в следующей программе класс TwoDShape используется для выведения класса Triangle. Обратите внимание на то, как объявляется класс Triangle. // Простая иерархия классов. using System; // Класс двумерных объектов. class TwoDShape { public double width; public double height; public void showDimO { Console.WriteLine("Ширина и высота равны " + width + " и " + height); > ) II Класс Triangle выводится из класса TwoDShape. class Triangle : TwoDShape \ public string style; // Тип треугольника. // Метод возвращает площадь треугольника, public double area() { return width * height / 2; } // Отображаем тип треугольника, public void showStyleO { Console.WriteLine("Треугольник " + style); > } class Shapes { public static void Main() ( Triangle tl - new Triangle(); Triangle t2 = new Triangle(); tl.width = 4.0; tl.height = 4.0; tl.style = "равнобедренный"; t2.width = 8.0; t2.height - 12.0; t2.style - "прямоугольный"; Console.WriteLine("Информация о tl: "); tl.showStyleO ; tl.showDimt); Console.WriteLine("Площадь равна " + tl.area{)); Console.WriteLine(); Console.WriteLine("Информация о t2: "); 12.showStyleO ; t2.showDira(); Console.WriteLine("Площадь равна " + t2.area()); ) } Вот результаты работы этой программы. Информация о t1: Треугольник равнобедренный Ширина и высота равны 4 и 4 Площадь равна 8 Информация о t2: Треугольник прямоугольный Ширина и высота равны 8 и 12 Площадь равна 48 В классе Triangle создается специфический тип объекта класса TwoDShape, в данном случае треугольник. Класс Triangle содержит все элементы класса TwoDShape и, кроме того, поле style, метод area () и метод showStyle О. В переменной style хранится описание типа треугольника, метод area о вычисляет и возвращает его площадь, а метод showStyle () отображает данные о типе треугольника. Ниже приведен синтаксис, который используется в объявлении класса Triangle, чтобы сделать его производным от класса TwoDShape. | class Triangle : TwoDShape {Этот синтаксис можно обобщить. Если один класс наследует другой, то имя базового класса указывается после имени производного, причем имена классов разделяются двоеточием. В С# синтаксис наследования класса очень прост для запоминания и использования. Поскольку класс Triangle включает все члены базового класса, TwoDShape, он может обращаться к членам width и height внутри метода агеа(). Кроме того, внутри метода Main () объекты tl и t2 могут прямо ссылаться на члены width и height, как если бы они были частью класса Triangle. Несмотря на то что класс TwoDShape является базовым для класса Triangle, это совершенно независимый и автономный класс. То, что его использует в качестве базового производный класс (классы), не означает невозможность использования его самого. Например, следующий фрагмент кода абсолютно легален:
TwoDShape shape = new TwoDShape(); shape.width = 10; shape.height = 20; shape.showDim();
Безусловно, объект класса TwoDShape "ничего не знает" и не имеет права доступа К классу, производному от TwoDShape. Общая форма объявления класса, который наследует базовый класс, имеет такой вид: class имя_производного_класса : имя_базо&ого_класса { // тело класса }
Для создаваемого производного класса можно указать только один базовый класс. В С# (в отличие от С++) не поддерживается наследование нескольких базовых классов в одном производном классе. Этот факт необходимо учитывать при переводе С++-кода на С#. Однако можно создать иерархию наследования, в которой один производный класс становится базовым для другого производного класса. И конечно же, ни один класс не может быть базовым (ни прямо, ни косвенно) для самого себя. Основное достоинство наследования состоит в том, что, создав базовый класс, который определяет общие атрибуты для множества объектов, его можно использовать для создания любого числа более специализированных производных классов. В каждом производном классе можно затем точно "настроить" собственную классификацию. Вот, например, как из базового класса TwoDShape можно вывести производный класс, который инкапсулирует прямоугольники: // Класс прямоугольников Rectangle, производный //от класса TwoDShape. class Rectangle : TwoDShape { // Метод возвращает значение true, если // прямоугольник является квадратом, public bool isSquare О { if(width == height) return true; return false; ) II Метод возвращает значение площади прямоугольника, public double area О ( return width * height; ) } Класс Rectangle включает класс TwoDShape и добавляет метод isSquareO, который определяет, является ли прямоугольник квадратом, и метод агеа(), вычисляющий площадь прямоугольника. Полиморфизм.
Полиморфизм (от греческого слова polymorphism, означающего "много форм") — это качество, которое позволяет одному интерфейсу получать доступ к целому классу действий. Простым примером полиморфизма может послужить руль автомобиля. Руль (интерфейс) остается рулем независимо от того, какой тип рулевого механизма используется в автомобиле. Другими словами, руль работает одинаково в любом случае: оснащен ли ваш автомобиль рулевым управлением прямого действия, рулевым управлением с усилителем или реечным управлением. Таким образом, поворот руля влево заставит автомобиль поехать влево независимо от типа используемого в нем рулевого управления. Достоинство такого единообразного интерфейса состоит, безусловно, в том, что, если вы знаете, как обращаться с рулем, вы сможете водить автомобиль любого типа. Тот же принцип можно применить и к программированию. Рассмотрим, например, стек (stack), т.е. область памяти, функционирующую по принципу "последним пришел — первым обслужен". Предположим, вы пишете программу, для которой нужно организовать три различных типа стека. Один стек предназначен для целочисленных значений, второй — для значений с плавающей точкой, а третий — для символов. В этом случае для реализации каждого стека используется один и тот же алгоритм, несмотря на различие в типах сохраняемых данных. В случае не объектно-ориентированного языка вам пришлось бы создать три набора "стековых" подпрограмм, имеющих различные имена. Но благодаря полиморфизму в среде С# можно создать один общий набор "стековых" подпрограмм, который обрабатывает все три типа стека. Иными словами, зная, как использовать один стек, можно использовать все остальные. Концепцию полиморфизма часто выражают такой фразой: "один интерфейс — много методов". Это означает, что для выполнения группы подобных действий можно разработать общий интерфейс. Полиморфизм позволяет понизить степень сложности программы, предоставляя программисту возможность использовать один и тот же интерфейс для задания общего класса действий. Конкретное (нужное в том или ином случае) действие (метод) выбирается компилятором. Программисту нет необходимости делать это вручную. Его задача — правильно использовать общий интерфейс.
Просмотров: 4541 |