Учебное пособие (1077022), страница 10
Текст из файла (страница 10)
Так как данныеполя не доступны снаружи класса, они объявлены в виде обычных полей, ане в виде свойств.Класс включает в себя конструктор, присваивающий значениеширины и высоты полям данных класса. Также инициализируетсясвойство Type, унаследованное от абстрактного класса.ДалееобъявленунаследованнойотабстрактногоклассаГеометрическая фигура метод Area. Поскольку данный метод былобъявлен как абстрактный, то он автоматически является виртуальным идолжен быть переопределен с ключевым словом override.Затем объявлен метод Print, унаследованный от интерфейса IPrint.Данный метод выводит в консоль результат работы метода ToString.Поскольку метод ToString не переопределялся в текущем классе, то егореализация берется из родительского класса, которым в данном случаеявляется абстрактный класс Геометрическая фигура.4.9.4 Класс «Квадрат»Класс Квадрат наследуется от класса Прямоугольник и реализуетинтерфейс IPrint:usingusingusingusingSystem;System.Collections.Generic;System.Linq;System.Text;80namespace Figures{class Square : Rectangle, IPrint{public Square(double size): base(size, size){this.Type = "Квадрат";}}}Данный класс использует геометрическое определение квадрата, какпрямоугольника с одинаковыми сторонами.Вэтомклассефактическиреализовантолькоконструктор,принимающий сторону квадрата в качестве параметра.
В начале работыконструктор класса Квадрат вызывает конструктор базового класса«base(size, size)», которым в данном случае является класс Прямоугольник.Сторона квадрата передается как длина и ширина прямоугольника вконструктор базового класса. В теле конструктора инициализируетсятолько свойство Type.Не смотря на то, что класс реализует интерфейс IPrint, в нем несодержится метода Print, так как этот метод унаследован от родительскогокласса.4.9.5 Класс «Круг»Класс Круг наследуется от абстрактного класса Геометрическаяфигура и реализует интерфейс IPrint:usingusingusingusingSystem;System.Collections.Generic;System.Linq;System.Text;namespace Figures{class Circle : Figure, IPrint{/// <summary>81/// Ширина/// </summary>double radius;/// <summary>/// Основной конструктор/// </summary>/// <param name="ph">Высота</param>/// <param name="pw">Ширина</param>public Circle(double pr){this.radius = pr;this.Type = "Круг";}public override double Area(){double Result = Math.PI * this.radius * this.radius;return Result;}public void Print(){Console.WriteLine(this.ToString());}}}Реализация данного класса очень похожа на реализацию классаПрямоугольник, но в качестве полей данных хранится только радиусокружности, а площадь определяется по формуле площади круга.4.9.6 Основная программаОсновная программа содержит примеры создания объектов классов ивывод информации о них с помощью метода Print, унаследованного отинтерфейса IPrint:using System;using System.Linq;using System.Text;namespace Figures{class Program{static void Main(string[] args)82{Rectangle rect = new Rectangle(5, 4);Square square = new Square(5);Circle circle = new Circle(5);rect.Print();square.Print();circle.Print();Console.ReadLine();}}}В консоль будет выведено:Прямоугольник площадью 20Квадрат площадью 25Круг площадью 78,53981633974484.10 Контрольные вопросы к разделу 41.
Как объявить конструктор класса в языке C#?2. Как объявить метод класса в языке C#?3. Какие области видимости существуют в языке C#?4. Что такое свойства и для чего они используются?5. Что такое опорная переменная свойства?6. Как используются get-аксессор и set-аксессор свойства?7. Как задаются области видимости для свойств и аксессоров?8.
Приведите пример задания автоопределяемого свойства.9. Приведите пример задания вычисляемого свойства.10.Как объявить деструктор класса в языке C#?11.Как объявить статические элементы класса в языке C#?12.Как используется конструкция using static в языке C#?13.Как реализуется наследование класса от класса?14.Как из конструктора класса вызвать конструктор базовогокласса?8315.Как из конструктора класса вызвать другой конструктортекущего класса?16.Как переопределить виртуальный метод?17.В чем разница между ключевыми словами override и new припереопределении виртуального метода?18.Вчемсходстваиразличиямеждувиртуальнымииабстрактными методами?19.Что такое абстрактный класс?20.Как в Visual Studio сгенерировать заглушки методов принаследовании от абстрактного класса?21.Что такое интерфейсы и для чего они используются в языке C#?22.Вчемсходстваиразличиямеждуинтерфейсамииабстрактными классами?23.Можно ли в языке C# унаследовать класс от несколькихклассов? От нескольких интерфейсов? Почему?24.Как реализуется наследование класса от класса и интерфейсов?25.Являютсялиметоды,унаследованныеотинтерфейсов,виртуальными?26.Как в Visual Studio сгенерировать заглушки методов принаследовании от интерфейса?27.В чем разница между «реализацией интерфейса» и «явнойреализацией интерфейса»?28.Что такое методы расширения и как они реализуются в языкеC#?29.Что такое частичные классы и как они реализуются в языке C#?30.Как создать диаграмму классов в Visual Studio?845 Расширенные возможности объектноориентированного программирования в языке C#Помимо базовых возможностей ООП, связанных с созданием классови интерфейсов и их наследованием, в языке C# существует большоеколичество расширенных возможностей, и некоторые из них являютсяуникальными особенностями языка C#.5.1 ПеречисленияПеречисление (enumeration, enum) – это множество целых чисел, закаждым из которых закреплена строковая константа.Перечисление позволяет перечислить множество значений какоголибо свойства.В классическом языке С аналогом перечислений были объявленияконстант с помощью директивы препроцессора #define.
Достаточно быстропрограммисты на языке С стали объявлять константы с «иерархическими»именами, в имя константы входили и наименование перечисления инаименование конкретного значения. В дальнейшем это привело кпоявлению перечислений, использующихся в языках C++, Java и C#.Рассмотрим работу с перечислениями на основе фрагментов примера5.Пример объявления перечисления в C#:/// <summary>/// Перечисление/// </summary>public enum СтороныСвета{Север, Юг, Запад, Восток}При таком объявлении символьным константам Север, Юг, Запад,Восток присваиваются целые значения, начиная с 0.85Поскольку в языке C# используются символы в формате Unicode, тоимена переменных, классов, перечислений и других структур можнозадавать на русском языке, как сделано в данном примере.Присваивать значения символическим константам можно явно.Пример перечисления с присвоением значений:/// <summary>/// Перечисление с присвоением значений/// </summary>public enum СтороныСвета2{Север = 0,Юг =1,Запад = 3,Восток = 4}Использование перечислений облегчает понимание кода при проверкеусловий.Пример использования перечислений при проверке условия:СтороныСвета temp1 = СтороныСвета.Восток;if (temp1 == СтороныСвета.Восток){Console.WriteLine("Восток");}Перечисления в языке C# имеют интересную возможность – значениеперечисления можно получить по текстовой строке, содержащей текстсимволической константы:СтороныСвета temp2 = (СтороныСвета)Enum.Parse(typeof(СтороныСвета),"СЕВЕР", true);Метод Enum.Parse преобразует строковое значение в значениеперечисления.
Первым параметром является тип данных перечисления,вторым – преобразуемая строка, третьим – логическое значение котороепоказывает нужно ли игнорировать регистр символов строки припреобразовании.В данном случае регистр символов строки «СЕВЕР» не точносоответствуетзначениюперечисления,нопреобразованиебудет86выполнено успешно, так как третий параметр содержит истинное значение.В результате преобразования переменная temp2 будет содержать значение«СтороныСвета.Север».5.2 Перегрузка операторовПовозможностямперегрузкиоператоровязыкC#занимаетпромежуточное значение между Java и C++.В языке Java перегрузка операторов не используется.
Предполагается,что программист на языке Java должен применять методы классов вместоперегруженных операторов.Язык C++ обладает богатыми возможностями перегрузки операторов.Перегрузка операторов в С++ разделяется на внутреннюю (когдаперегружаемый оператор объявляется как метод экземпляра класса) ивнешнюю (когда перегружаемый оператор объявляется как статическийметод класса).В языке C# есть только аналог внешней перегрузки операторов С++.Рассмотрим перегрузку операторов на основе фрагментов примера 6.Пример класса, в котором перегружены основные операторы:usingusingusingusingSystem;System.Collections.Generic;System.Linq;System.Text;namespace Operators{/// <summary>/// Пример класса для перегрузки операторов/// </summary>public class Number{/// <summary>/// Целое число/// </summary>public int Num { get; protected set; }/// <summary>/// Конструктор87/// </summary>public Number(int param){this.Num = param;Console.WriteLine("Вызов конструктора для {0}", param);}/// <summary>/// Приведение к строке/// </summary>public override string ToString(){return this.Num.ToString();}/// <summary>/// Перегрузка унарного оператора/// Префиксную и постфиксную формы компилятор/// различает автоматически/// </summary>public static Number operator ++(Number lhs){//Не нужно изменять вызываемый объект//lhs.Num++;//return lhs;return new Number(lhs.Num+1);}/// <summary>/// Перегрузка бинарного оператора для (Number + Number)/// </summary>public static Number operator + (Number lhs, Number rhs){int newNum = lhs.Num + rhs.Num;Number Result = new Number(newNum);return Result;//return new Number(lhs.Num + rhs.Num);}/// <summary>/// Перегрузка бинарного оператора для (Number + int)/// </summary>public static Number operator +(Number lhs, int rhs){return new Number(lhs.Num + rhs);}/// <summary>88/// Метод как аналог внутренней перегрузки/// </summary>public void AddInt(int param){this.Num += param;}/// <summary>/// Аналог внутренней перегрузки/// без создания нового объекта/// </summary>public static Number operator *(Number lhs, int rhs){lhs.Num = lhs.Num * rhs;return lhs;}//Перегрузка операторов сравнения должна производиться попарно// == и !=// > и <// => и <=public static bool operator == (Number lhs, Number rhs){return lhs.Num == rhs.Num;}public static bool operator != (Number lhs, Number rhs){return !(lhs == rhs);}//Если переопределяется оператор ==, то необходимо переопределитьследующие методыpublic override bool Equals(object obj){Number param = (Number)obj;return this == param;}public override int GetHashCode(){return this.Num.GetHashCode();}//Перегрузка операторов неравенстваpublic static bool operator < (Number lhs, Number rhs){return lhs.Num < rhs.Num;89}public static bool operator > (Number lhs, Number rhs){return lhs.Num > rhs.Num;}public static bool{return lhs.Num}public static bool{return lhs.Num}operator <= (Number lhs, Number rhs)<= rhs.Num;operator >= (Number lhs, Number rhs)>= rhs.Num;//Операторы приведения типов//Для одного типа можно задать или явное или неявное приведение/// <summary>/// Оператор явного приведения типа Number к типу int/// </summary>public static explicit operator int(Number lhs){return lhs.Num;}/// <summary>/// Оператор неявного приведения типа Number к типу double/// </summary>public static implicit operator double(Number lhs){return (double)lhs.Num;}/// <summary>/// Пример индексатора/// </summary>public int this[int i]{get{//Возможный доступ к i-му элементу встроенного массиваreturn this.Num + i;}set{//Возможный доступ к i-му элементу встроенного массиваthis.Num = value + i;}}90}}Класс содержит свойство Num, которое используется в качествеосновыдляперегруженныхоператоровиконструктор,инициализирующий данное свойство.














