Главная arrow Язык программирования C# arrow C# Полное руководство Герберт Шилдт arrow Основы наследования C# Полное руководство Герберт Шилдт

Основы наследования C# Полное руководство Герберт Шилдт

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

// Класс для двумерных объектов.

class TwoDShape {
   public double Width;
   public double Height;

   public void ShowDim() {
      Console.WriteLine("Ширина и высота равны " +
                                       Width + " и " + Height);
   }
}


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

// Пример простой иерархии классов.

using System;

// Класс для двумерных объектов.
class TwoDShape {
   public double Width;
   public double Height;
   public void ShowDim() {

      Console.WriteLine("Ширина и высота равны " + Width + " и " + Height);
   }
}

// Класс Triangle, производный от класса TwoDShape.
class Triangle : TwoDShape {
   public string Style; // тип треугольника

   // Возвратить площадь треугольника.
   public double Area() {
      return Width * Height / 2;
   }

   // Показать тип треугольника, public void ShowStyle() {
      Console.WriteLine("Треугольник " + Style);
   }
}

class Shapes {
   static void Main() {
      Triangle t1 = new Triangle();
      Triangle t2 = new Triangle();

      t1.Width = 4.0;
      t1.Height = 4.0;
      t1.Style = "равнобедренный";

      t2.Width = 8.0;
      t2.Height = 12.0;
      t2.Style = "прямоугольный";

      Console.WriteLine("Сведения об объекте t1: ");
      t1.ShowStyle();
      t1. ShowDim () ;
      Console.WriteLine("Площадь равна " + t1.Area());
      
      Console.WriteLine ();

      Console.WriteLine("Сведения об объекте t2: ");
      t2.ShowStyle ();
      t2.ShowDim () ;

      Console.WriteLine("Площадь равна " + t2.Area());
   }
}

При выполнении этой программы получается следующий результат:
   Сведения об объекте t1:
   Треугольник равнобедренный
   Ширина и высота равны 4 и 4
   Площадь равна 8

   Сведения об объекте t2:
   Треугольник прямоугольный
   Ширина и высота равны 8 и 12
   Площадь равна 48

В классе Triangle создается особый тип объекта класса TwoDShape (в данном случае - треугольник). Кроме того, в класс Triangle входят все члены класса TwoDShape, к которым, в частности, добавляются методы Area () и ShowStyle (). Так, описание типа треугольника сохраняется в переменной Style, метод Area () рассчитывает и возвращает площадь треугольника, а метод ShowStyle () отображает тип треугольника.
Обратите внимание на синтаксис, используемый в классе Triangle для наследования класса TwoDShape:

class Triangle : TwoDShape {

Этот синтаксис может быть обобщен. Всякий раз, когда один класс наследует от другого, после имени базового класса указывается имя производного класса, отделяемое двоеточием. В C# синтаксис наследования класса удивительно прост и удобен в использовании.
В класс Triangle входят все члены его базового класса TwoDShape, и поэтому в нем переменные Width и Height доступны для метода Area (). Кроме того, объекты tl и t2 в методе Main () могут обращаться непосредственно к переменным Width и Height, как будто они являются членами класса Triangle. На рис. 11.1 схематически показано, каким образом класс TwoDShape вводится в класс Triangle.
Image
Рис. 11.1. Схематическое представление класса Triangle

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

TwoDShape shape = new TwoDShape();
shape.Width = 10;
shape.Height = 20;

shape.ShowDim();


Разумеется, объект класса TwoDShape никак не связан с любым из классов, производных от класса TwoDShape, и вообще не имеет к ним доступа.
Ниже приведена общая форма объявления класса, наследующего от базового класса.

class имя_производного_класса : имя_базового_класса {
// тело класса
}


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

// Класс для прямоугольников, производный от
// класса TwoDShape.
class Rectangle : TwoDShape {
   // Возвратить логическое значение true, если
   // прямоугольник является квадратом,
   public bool IsSquare() {
      if(Width == Height) return true;
      return false;
   }

   // Возвратить площадь прямоугольника,
   public double Area() {    ,
      return Width * Height;
   }
}


В класс Rectangle входят все члены класса TwoDShape, к которым добавлен метод IsSquare (), определяющий, является ли прямоугольник квадратом, а также метод Area (), вычисляющий площадь прямоугольника.