Рейтинговые книги
Читем онлайн C# 4.0: полное руководство - Герберт Шилдт

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 90 91 92 93 94 95 96 97 98 ... 294

  }

}

Вот к какому результату приводит выполнение этого кода.

Метод Who() в классе Base.

Метод Who() в классе Derived1

Метод Who() в классе Derived2

В коде из приведенного выше примера создаются базовый класс Base и два производных от него класса — Derived1 и Derived2. В классе Base объявляется виртуальный метод Who(), который переопределяется в обоих производных классах. Затем в методе Main() объявляются объекты типа Base, Derivedl и Derived2. Кроме того, объявляется переменная baseRef ссылочного типа Base. Далее ссылка на каждый тип объекта присваивается переменной baseRef и затем используется для вызова метода Who(). Как следует из результата выполнения приведенного выше кода, вариант выполняемого метода Who() определяется по типу объекта, к которому происходит обращение по ссылке во время вызова этого метода, а не по типу класса переменной baseRef.

Но переопределять виртуальный метод совсем не обязательно. Ведь если в производном классе не предоставляется собственный вариант виртуального метода, то используется его вариант из базового класса, как в приведенном ниже примере.

/* Если виртуальный метод не переопределяется, то используется его вариант из базового класса. */

using System;

class Base {

  // Создать виртуальный метод в базовом классе.

  public virtual void Who() {

    Console.WriteLine("Метод Who() в классе Base");

  }

}

class Derivedl : Base {

  // Переопределить метод Who() в производном классе.

  public override void Who() {

    Console.WriteLine("Метод Who() в классе Derivedl");

  }

}

class Derived2 : Base {

  // В этом классе метод Who() не переопределяется.

}

class NoOverrideDemo {

  static void Main() {

    Base baseOb = new Base();

    Derivedl dObl = new Derivedl();

    Derived2 d0b2 = new Derived2();

    Base baseRef; // ссылка на базовый класс

    baseRef = baseOb;

    baseRef.Who();

    baseRef = dObl;

    baseRef.Who() ;

    baseRef = d0b2;

    baseRef.Who(); // вызывается метод Who() из класса Base

  }

}

Выполнение этого кода приводит к следующему результату.

Метод Who() в классе Base.

Метод Who() в классе Derivedl

Метод Who() в классе Base

В данном примере метод Who() не переопределяется в классе Derived2. Поэтому для объекта класса Derived2 вызывается метод Who() из класса Base.

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

/* В многоуровневой иерархии классов выполняется тот переопределенный вариант виртуального метода, который обнаруживается первым при продвижении вверх по иерархии. */

using System;

class Base {

  // Создать виртуальный метод в базовом классе,

  public virtual void Who() {

    Console.WriteLine("Метод Who() в классе Base");

  }

}

class Derived1 : Base {

  // Переопределить метод Who() в производном классе.

  public override void Who() {

    Console.WriteLine("Метод Who() в классе Derived1");

  }

}

class Derived2 : Derived1 {

  // В этом классе метод Who() не переопределяется.

}

class Derived3 : Derived2 {

  //И в этом классе метод Who() не переопределяется.

}

class No0verrideDemo2 {

  static void Main() {

    Derived3 dOb = new Derived3();

    Base baseRef; // ссылка на базовый класс

    baseRef = dOb;

    baseRef.Who(); // вызов метода Who() из класса Derivedl

  }

}

Вот к какому результату приводит выполнение этого кода.

Метод Who() в классе Derived1

В данном примере класс Derived3 наследует класс Derived2, который наследует класс Derived1, а тот, в свою очередь, — класс Base. Как показывает приведенный выше результат, выполняется метод Who(), переопределяемый в классе Derived1, поскольку это первый вариант виртуального метода, обнаруживаемый при продвижении вверх по иерархии от классов Derived3 и Derived2, где метод Who() не переопределяется, к классу Derived1.

И еще одно замечание: свойства также подлежат модификации ключевым словом virtual и переопределению ключевым словом override. Это же относится и к индексаторам.

Что дает переопределение методов

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

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

Применение виртуальных методов

Для того чтобы стали понятнее преимущества виртуальных методов, применим их в классе TwoDShape. В предыдущих примерах в каждом классе, производном от класса TwoDShape, определялся метод Area(). Но, по-видимому, метод Area() лучше было бы сделать виртуальным в классе TwoDShape и тем самым предоставить возможность переопределить его в каждом производном классе с учетом особенностей расчета площади той двумерной формы, которую инкапсулирует этот класс. Именно это и сделано в приведенном ниже примере программы. Ради удобства демонстрации классов в этой программе введено также свойство name в классе TwoDShape.

// Применить виртуальные методы и полиморфизм-.

using System;

class TwoDShape {

  double pri_width;

  double pri_height;

  // Конструктор по умолчанию,

  public TwoDShape() {

    Width = Height = 0.0;

    name = "null";

  }

  // Параметризированный конструктор.

  public TwoDShape(double w, double h, string n) {

    Width = w;

    Height = h;

    name = n;

  }

  // Сконструировать объект равной ширины и высоты,

  public TwoDShape(double x, string n) {

    Width = Height = x;

    name = n;

  }

  // Сконструировать копию объекта TwoDShape.

  public TwoDShape(TwoDShape ob) {

    Width = ob.Width;

    Height = ob.Height;

    name = ob.name;

  }

  // Свойства ширины и высоты объекта,

1 ... 90 91 92 93 94 95 96 97 98 ... 294
На этой странице вы можете бесплатно читать книгу C# 4.0: полное руководство - Герберт Шилдт бесплатно.
Похожие на C# 4.0: полное руководство - Герберт Шилдт книги

Оставить комментарий