Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Public static implicit operator int(ThreeDopl)

Else

Else

return false;

}

// Перегрузкаоператора ">".

public static bool operator >(ThreeDopl, ThreeD op2)

{

if((opl.x> op2.x) && (opl.у> op2.y) &&

(opl.z> op2.z))

return true;

return false;

}

// ОтображаемкоординатыX, Y, Z.

publicvoidshow()

{

Console.WriteLine(x + ", " + у + ", " + z);

}

}

classThreeDDemo {

public static void Main() {

ThreeD a = new ThreeD(5, 6, 7);

ThreeD b = new ThreeD(10, 10, 10);

ThreeDс = new ThreeD(1, 2, 3);

Console.Write("Координатыточкиа: ");

a.show();

Console.Write("Координатыточки b: ");

b.show();

Console.Write("Координатыточкис: ");

с.show();

Console.WriteLine();

if(a > c) Console.WriteLine("a >с - ИСТИНА")

if(a < c) Console.WriteLine("a <с - ИСТИНА")

if(a > b) Console.WriteLine("a > b - ИСТИНА")

if(a < b) Console.WriteLine("a < b - ИСТИНА")

}

}

При выполнении эта программа генерирует такие результаты:

Координаты точки а: 5, 6, 7

Координаты точки Ь: 10, 10, 10

Координаты точки с: 1, 2, 3

а >с - ИСТИНА

а < b - ИСТИНА

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

Перегружая операторы " == " и " != ", следует перегрузить также методы Object.Equals() и Object.GetHashCode().

4.3.5 Операторы преобразования

 

Иногда объект класса нужно использовать в выражении, включающем другие типы данных. Такие средства может обеспечить перегрузка одного или нескольких операторов. Но в некоторых случаях желаемого результата можно достичь за счет преобразования типов (из классового в нужный). В целях обработки подобных ситуаций С# позволяет создавать специальный тип операторного метода operator, именуемого оператором преобразования. Такой оператор преобразует объект некоторого класса в значение другого типа. По сути, оператор преобразования перегружает оператор приведения типов. Операторы преобразования способствуют полной интеграции классовых типов в С# -среду программирования, позволяя объектам класса свободно смешиваться с данными других типов при условии определения операторов преобразования в эти "другие типы".

Существуют две формы операторов преобразования: явная и неявная. В общем виде они записываются так:

publicstaticexplicitoperatorтип_результата(исходный__типv) [return значение; ]

publicstaticimplicitoperatorтип_результата(исходный_типv) [returnзначение;]

Здесь элемент тип _ результата представляет собой тип, в который вы хотите выполнить преобразование; элемент исходный _ тип означает тип объекта, подлежащего преобразованию; элемент v — значение класса после преобразования. Операторы преобразования возвращают данные типа тип _ результата, причем спецификатор типа здесь указывать не разрешается.

Если оператор преобразования определен с ключевым словом implicit, преобразование выполняется автоматически, т.е. при использовании объекта в выражении, включающем данные типа тип _ резулътата. Если оператор преобразования определен с ключевым словом explicit, преобразование выполняется при использовании оператора приведения типов. Для одной и той же пары типов, участвующих в преобразовании, нельзя определить как explicit -, так и implicit -оператор преобразования.

Для иллюстрации определения и использования оператора преобразования создадим его для класса ThreeD. Предположим, необходимо преобразовать объект типа ThreeD в целочисленное значение, чтобы его можно было использовать в выражениях типа int. Это преобразование будет заключаться в вычислении произведения значений всех трех координат объекта. Для реализации такого преобразования используем implicit -форму оператора, который будет иметь такой вид:

{returnopl.x * opl.у * opl.z;}

4.3.6 Рекомендации и ограничения по созданию перегруженных операторов

 

Действие перегруженного оператора применительно к классу, для которого он определяется, не обязательно должно иметь отношение к стандартному действию этого оператора применительно к встроенным С #-типам. Но в целях структурированности и читабельности программного кода создаваемый перегруженный оператор должен по возможности отражать исходное назначение того или иного оператора. Например, оператор "+", перегруженный для класса ThreeD, концептуально подобен оператору "+", определенному для целочисленных типов. Ведь вряд ли есть логика в определении для класса, например, оператора "+", который по своему действию больше напоминает оператор деления (/). Таким образом, основная идея создания перегруженного оператора — наделить его новыми (нужными для вас) возможностями, которые тем не менее связаны с его первоначальным назначением.

На перегрузку операторов налагается ряд ограничений. Нельзя изменять приоритет оператора. Нельзя изменять количество операндов, принимаемых оператором, хотя операторный метод мог бы игнорировать любой операнд. Некоторые операторы вообще нельзя перегружать. Например, нельзя перегружать какие бы то ни было операторы присваивания (включая составные, например " += "). Ниже перечислены остальные операторы, перегрузка которых запрещена.

&& || [] () new is sizeof typeof? ->. =

Несмотря на то, что нельзя перегружать оператор приведения типов (()) в явном виде, можно создать операторы преобразования, которые, как было показано выше, успешно выполняют это.


4.4 Индексаторы

Индексация массивов реализуется с использованием оператора " [ ]". В своих классах можно перегрузить его, но не прибегая к "услугам" метода operator(), а посредством создания индексатора(indexer). Индексатор позволяетобеспечить индексированный доступ к объекту. Главное назначение индексаторов —поддержать создание специализированных массивов, на которые налагается одно или несколько ограничений. При этом индексаторы можно использовать в синтаксисе, подобном реализованному в массивах. Индексаторы могут характеризоваться одной или несколькими размерностями.

Одномерный индексатор имеет следующий формат.

тип_элементаthis[int индекс] {

// Аксессор считывания данных,

get {

// Возврат значения, заданного элементом индекс.

}

// Аксессор установки данных,

set {

// Установка значения, заданного

// элементом индекс.

}}

Здесь тип_элемента — базовый тип индексатора. Таким

образом, тип_элемента — это тип каждого элемента, к которому предоставляется доступ посредством индексатора. Он соответствует базовому типу массива. Параметр индекс получает индекс опрашиваемого (или устанавливаемого) элемента. Строго говоря, этот параметр не обязательно должен иметь тип int, но поскольку индексаторы обычно используются для обеспечения индексации массивов, целочисленный тип —наиболее подходящий.

В теле индексатора определяются два аксессора (средства доступа) с именами get и set. Аксессорподобен методу за исключением того, что в нем отсутствует объявлениетипа возвращаемого значения и параметров. При использовании индексатора аксессоры вызываются автоматически, и в качестве параметра оба аксессора принимают индекс. Если индексатор стоит слева от оператора присваивания, вызывается аксессорset и устанавливается элемент, заданный параметром индекс. В противном случае вызывается аксессорget и возвращается значение, соответствующее параметру индекc. Метод set также получает значение (именуемое value), которое присваивается элементу массива, найденному по заданному индексу.

Одно из достоинств индексатора состоит в том, что он позволяет точно управлять характером доступа к массиву, "отбраковывая" попытки некорректного доступа. Рассмотрим пример. В следующей программе класс FailSoftArray реализует массив, который "вылавливает" ошибки нарушения границ, предотвращая возникновение исключительных ситуаций. Это достигается за счет инкапсуляции массива как закрытого члена класса и осуществления доступа к этому массиву только через индексатор.

 

// Использование индексатора для создания

// отказоустойчивого массива.

using System;

classFailSoftArray {

int[] a; // Ссылканамассив.

publicint Length; // Length - открытыйчлен.

publicboolerrflag; // Индикаторрезультата

// последней операции.

// Создаем массив заданного размера,

publicFailSoftArray(int size) {

a = new int[size];Length = size;}

// Это - индексатор для класса FailSoftArray.

publicint this[int index] {

// Это - get-аксессор.

get {if(ok(index)) {errflag = false;return a[index];}

else {errflag = true;return 0;}

}

// Это - set-аксессор.

set {if(ok(index)) {a[index] = value;errflag = false;}

elseerrflag = true;}

}

// Методвозвращаетзначениеtrue, если

// индекс - в пределах границ,

privatebool ok(int index) {

if(index >= 0 & index < Length) return true;

returnfalse;

}

}

// Демонстрируемотказоустойчивыймассив,

classFSDemo {

public static void Main() {

FailSoftArrayfs = new FailSoftArray(5);

int x;

Console.WriteLine("Мягкоеприземление. ");

for(inti=0; i< (fs.Length * 2);i++)fs[i] = i*10;

for(inti=0; i< (fs.Length * 2);i++)

{x = fs[i];if(x!= -1) Console.Write(x + " ");}

Console.WriteLine();

// Теперь генерируем некорректный доступ.

Console.WriteLine("\nРабота с уведомлением об ошибках.");

for(inti=0; i< (fs.Length * 2); i++) {

fs[i] * i*10;if(fs.errflag)

Console.WriteLine("fs[" + i + "] внеграниц");

}

for(inti=0; i< (fs.Length * 2);i++){

x = fs[i];if(!fs.errflag) Console.Write(x + " ");

elseConsole.WriteLine("fs[" + i + "] внеграниц");

}

}

}

При выполнении этой программы получаем такие результаты:

"Мягкое приземление".

0 10 20 30 40 0 0000

Работа с уведомлением об ошибках.

fs[5] вне границ

fs[6] вне границ

fs[7] вне границ

fs[8] вне границ

fs[9] вне границ

0 10 20 30 40 fs[5] вне границ

fs[6] вне границ

fs[7] вне границ

fs[8] вне границ

fs[9] вне границ

 

Аксессорget предотвращает ошибки нарушения границ. Если заданный индекс находится в пределах границ, аксессорget возвращает элемент, соответствующий этому индексу. А если переданный индекс выходит за пределы границ, операции с массивом не выполняются, но и ничего страшного при этом не происходит. В данной версии класса FailSoftArray переменная errflag содержит результат выполнения каждой операции. Чтобы узнать, как завершилась очередная операция, достаточно проанализировать это поле.

Аксессорset () предотвращает ошибки нарушения границ. Если заданный индекс находится в пределах границ, значение, переданное через переменную value, присваивается соответствующему элементу массива. В противном случае признак ошибки errflag устанавливается равным значению true.

Индексаторы необязательно создавать с поддержкой как get -, так и set-аксессоров. Можно создать индексатор, предназначенный только для чтения, реализовав лишь get - аксессор. И точно также можно создать индексатор, предназначенный только для записи, реализовав лишь set - аксессор.

Индексаторы можно перегружать. Чаще всего индексатор перегружается, чтобы иметь возможность использовать объект класса в качестве индекса, значение которого вычисляется специальным образом.

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

На использование индексаторов накладывается два ограничения. Во-первых, поскольку в индексаторе не определяется область памяти, получаемое индексатором значение нельзя передавать методу в качестве ref - или out - параметра. Во-вторых, индексатор должен быть членом экземпляра своего класса, поэтому его нельзя объявлять с использованием ключевого слова static.

Можно создавать индексаторы и для многомерных массивов.

4.5 Свойства

Свойство — это специальный тип членов класса, который включает поле, и методы доступа к этому полю.Часто требуется создать поле, которое должно быть доступно для пользователей объекта,но программист при этом хочет осуществлять управление операциями, разрешенными к выполнению над этим полем. Например, по некоторым обстоятельствам вы желаете ограничить диапазон значений, которые можно присваивать этому полю. Несмотря на то, что этого можно достичь с помощью закрытой переменной и методов доступа к ней, свойство предлагает более удобный и простой способ решения этой задачи.

Свойства во многом напоминают индексаторы. Свойство состоит из имени и пары аксессоров(get и set).Аксессоры используются для чтения содержимого переменной и записи в нее нового значения. Основное достоинство свойства состоит в том,что его имя можно использовать в выражениях и инструкциях присваивания подобно обычной переменной, хотя в действительности здесь будут автоматически вызываться get- и set-аксессоры. Автоматический вызов аксессоров и роднит свойства с индексаторами.

Формат записи свойства таков:

ТИП ИМЯ{

get{

// код аксессора чтения поля

}

set{

// код аксессора записи поля

}

Здесь ТИП — это тип свойства (например, i n t), а имя — его имя. После определения свойства любое использование его имени означает вызов соответствующего аксессора. Аксессорset автоматически принимает параметр с именем value, который содержит значение, присваиваемое свойству.

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

Пример, в котором определяется свойство myprop, используемое для доступа к полю prop. Это свойство позволяет присваивать полю только положительные числа.

// Пример использования свойства,

usingSystem;

classSimpProp {

intprop; // Это поле управляется свойством myprop.

publicSimpProp() { prop = 0; }

/* Это свойство поддерживает доступ к закрытой

<== предыдущая лекция | следующая лекция ==>
Public static ThreeD operator -(ThreeD op) | Попытка присвоить -10 свойству ob.myprop
Поделиться с друзьями:


Дата добавления: 2014-01-06; Просмотров: 527; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.067 сек.