Вызов базовых версий функций

В С# предусмотрен специальный синтаксис вызова базовых версий метода из производного класса: base.<MethodName> ( ). Например, если необходимо, чтобы метод производного класса возвращал значение в 5 раз большее чем, метод базового класса, можно воспользоваться следующим синтаксисом:

class class1

{

private int a=10;

public virtual int get _a()

{

return a;

}

}

class class2: class1

{

public override int get_a()

{

return base. get _a() * 5;

}

}

class Program

{

static void Main(string[] args)

{

class1 my_class1 = new class1();

class2 my_class2 = new class2();

Console.WriteLine(my_class1. get _a());

Console.WriteLine(my_class2. get _a());

Console.ReadLine();

}

}

Отметим, что синтаксис base.<MethodName> () можно использовать для вызов любого метода базового класса — вы не обязаны вызывать его только из переопреде­ленной версии того же метода.

Абстрактные классы и функции

Язык С# позволяет объявлять абстрактными и классы и функции. Нельзя созда­вать экземпляры абстрактных классов, в то время как абстрактные функции не имеют реализации и должны быть переопределены в любом неабстрактном классе-наслед­нике. Очевидно, что абстрактные функции автоматически являются виртуальными (хотя вы не должны применять ключевое слово virtual, так как это приведет к син­таксической ошибке). Если любой класс содержит любую абстрактную функцию, этот класс сам является абстрактным и должен быть объявлен таковым.

abstract class class1

{

public int a, b;

public class1()

{

Console.WriteLine("ВВедите числа");

a = Convert.ToInt32(Console.ReadLine());

b = Convert.ToInt32(Console.ReadLine());

}

public abstract void sum(int c, int d);

}

class class2 : class1

{

public override void sum(int c, int d)

{

int q = c + d;

Console.WriteLine("Сумма равна" + q);

}

}

class Program

{

static void Main(string[] args)

{

class2 myClass2 = new class2();

myClass2.sum(myClass2.a, myClass2.b);

Console.ReadLine();

}

}

Для создания абстактного метода необходимо в заголовок метода добавить ключевое слово abstract. Абстрактые классы не могут иметь объектов т.к. его методы не имеют реализации.

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

Структуры не предназначены для наследования. То есть наследовать от структуры нельзя. Единственное исключение состоит в том, что структуры, как и все другие типы С#, в конечном итоге наследуются от класса System.Object. Поэтому структуры доступ к методам класса System.Object и даже могут переопределять их. Действительная цепочка наследования, которая приводит к структуре, состоит в том, что структура наследуется от класса System.ValueType, который, в свою очередь наследуется от System.Object.ValueType, который не добавляет новых членов Object, но представляет реализацию ряда из них более подходящим для структуры способом. Отметим, что невозможно выбрать произвольный базовый класс для структуры все они наследуются от ValueType.

Полиморфизм

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

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

Вначале постараемся определить классы, которые понадобятся в программе. Для этого перефразируем предложения, выделяя существительные: Чертеж состоит из набора фи­гур (Shape). Фигура может быть окружностью (Circle), прямоугольником (Rectangle), треу­гольником (Triangle) и т. д. Соответственно, нужно реализовать класс Shapeи несколько подклассов. В данном случае достаточно ограничиться тремя подклассами: Circle, Rectangle и Triangle,как показано на рисунке.

Вызов базовых версий функций - student2.ru

По мере того как необходимо добавлять фигуры к чертежу, в программе создаются соответствующие объекты Shape(в данном случае Circles, Rectangles и Triangles).Свой­ства каждого объекта Shapeсохраняются внутри него. Для хранения объектов необходимо создать соответствующий массив.

Как же разные объекты могут быть размещены в одном массиве, если все его эле­менты должны иметь один тип? Поскольку Circle, Squareи Triangle— потомки Shape, любой из объектов этих трех типов может быть помещен в переменную типа Shape. Чтобы нарисовать объект, можно было бы написать метод в отдельном классе DrawingMachineи назвать его MakeDrawing.Этот метод перебирал бы объекты в мас­сиве, просматривал значения их переменных экземпляра и определял позицию, размер и форму объекта. Такой подход был бы неудобен, поскольку параметры и алгоритмы рисования объектов различны. Например, окружности нужен радиус и координаты цен­тра, прямоугольнику — высота и ширина, а более замысловатым формам может пона­добиться и большее число параметров.

Здесь и стоит обратиться к полиморфизму. Полиморфизм позволяет реализовать следующую методику: вместо того, чтобы раз­бираться извне, как следует рисовать каждый объект, стоит позволить объекту самому поддерживать свой алгоритм рисования. Каждый объект будет инкапсулированным па­кетом, содержащим данные и действия, необходимые для его отображения. Назовем метод, выводящий объект на экран, DrawYourself.Он нужен объекту любой формы, поэтому его необходимо объявить в классе Shape.Однако, неизвестна реализация DrawYourselfдля Shape.Поэтому DrawYourselfнужно объявить abstractв классе Shape,а затем вклю­чить его реализацию в каждом из трех подклассов.

Напомним, что абстрактный метод одновременно виртуален, и если переопределить DrawYourselfв каждом классе, производном от Shape,сработает механизм динамичес­кого связывания. Это означает, что для рисования объектов достаточно просто вызы­вать метод DrawYourselfкаждого из них. Механизм динамического связывания опреде­лит, Какого типа объект хранится в каждом элементе массива, и автоматически вызовет соответствующий метод DrawYourself.

Следует отметить, что DrawYourselfобъявлен abstractв классе Shape и пе­реопределен в каждом из трех подклассов. Подклассы просты и не содержат информа­ции о положении или размерах. Они просто выводят фигуру на экран.

public abstract class Shape

{

public abstract void DrawYouself();

}

public class Triangle : Shape

{

public override void DrawYouself()

{

Console.WriteLine(" * ");

Console.WriteLine(" * * ");

Console.WriteLine(" * * ");

Console.WriteLine(" *______* ");

}

}

public class Circle : Shape

{

public override void DrawYouself()

{

Console.WriteLine(" *** ");

Console.WriteLine(" * * ");

Console.WriteLine(" * * ");

Console.WriteLine(" * * ");

Console.WriteLine(" *** ");

}

}

public class Rectangle : Shape

{

public override void DrawYouself()

{

Console.WriteLine(" ******* ");

Console.WriteLine(" * * ");

Console.WriteLine(" * * ");

Console.WriteLine(" * * ");

Console.WriteLine(" ******* ");

}

}

class Program

{

static void Main(string[] args)

{

Shape myShape;

myShape = new Circle();

myShape.DrawYouself();

myShape = new Triangle();

myShape.DrawYouself();

myShape = new Rectangle();

myShape.DrawYouself();

Console.ReadLine();

}

}

Объявленная в переменная myShape принадлежит типу Shape. Поэтому myShape может ссылаться на объекты классов Circle, Triangle и Rectangle, производных от Shape.

Несмотря на то для переменной вызывается один и тот же метод DrawYourself из переменной myShape, благодаря механизму динамического связывания в каждой из них исполняется своя реализация метода DrawYourself. При вызове myShape.DrawYourself() программисту не приходится задумываться, какой объект хранится в myShape, и о других деталях. Полиморфизм позволяет рисо­вать чертеж на высоком уровне абстракции.

Наши рекомендации