Главная » C# » Использование свойств С# в приложении обмена валют в Visual C# (Sharp)

0

До сих пор тестовый код обращался к члену данных, как в следующей строке кода:

els.ExchangeRate – 123.45;

А члены данных реализовывались следующим образом:

public abstract class CurrencyTrader { public double ExchangeRate;

}

Предоставление  члена  данных  в  общей  области   видимости  было  приемлемым в предыдущих примерах, но, по правде говоря, мы не хотим делать этого, т. к. этим мы открываем внутреннее состояние объекта. А в объектно-ориентированном прраммировании предоставление внутреннего состояния является плохой идеей (пему, будет объяснено более подробно немного позже).’

Поэтому, вместо предоставления члена данных открытым образом, мы изменим тестовый код для того, чтобы делать это с помощью свойств. Хотя  использование свойств также открывает внутреннее состояние объекта, но они предоставляют долнительный уровень абстракции. Как мы узнаем далее, некоторые свойства проставляют как внутреннее, так и внешнее состояние. К таким свойствам относится свойство  ExchangeRate, которое  мы  используем  для  обращения  к  курсу  валют и изменения его. Если не использовать свойство ExchangeRate, то нам придется создать по методу для присвоения и получения значения курса валют. Эти методы работают подобно свойствам, но их не так удобно применять.

Модификация тестового кода для применения свойств

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

Модифицированный класс CurrencyTrader, предоставляющий ExchangeRate В кестве свойства С#, показан на рис. 6.3.

Рис. 6.3. Предоставление ExchangeRate в качестве свойства С#

Чтобы полностью ввести в заблуждение тест, имя свойства должно быть идентиым имени ранее объявленного члена данных. Чтобы избежать коллизии идентикаторов, член данных ExchangeRate переименован В _exchangeRate, а область видимости изменена с общей (public) на частную (private).

Свойства выглядят как методы без параметров, но возвращают значение. Кроме этого, каждое свойство должно иметь, по крайней мере, блок get или блок set (мут присутствовать оба блока), которые называются getter (получатель) и setter (уановщик) соответственно. Свойства, имеющие лишь блок get, доступны только для чтения. А свойства, имеющие только блок set, можно только устанавливать. В контексте свойства имеются лишь ключевые слова get или set. Никакого друго кода добавить нельзя.

Следующий оператор выполняет код,  определенный в блоке get, и получает стояние из класса, присваивая его значение переменной:

value = els.ExchangeRate;

А следующая строчка выполняет код, определенный в блоке set, и присваивает состояние из переменной классу:

els.Exchange = value;

Блок каждого из этих двух типов имеет свои особенности. Блок get должен всегда возвращать данные вызывающему коду, для чего требуется применение ключевого слова return. Блок  set не обязан делать ничего. Но если необходимо знать, какие

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

Проблемы свойств

Многие программисты считают, что использование свойств способствует распртранению плохих навыков программирования,  т. к. свойства делают возможным доступ к внутреннему состоянию объекта. В предыдущем исходном коде можно видеть, что член данных _exchangeRate имеет взаимно-однозначное соответствие со свойством ExchangeRate. Если вызывающий код присваивает значение свойству ExchangeRate, то  сразу  же  присваивается  значение  и  частному  члену  данных

_exchangeRate. Таким образом, обнажается, хотя и непрямым образом, внутреннее состояние. В качестве примера рассмотрим следующую ситуацию. Скажем, вы рили испечь что-то в электродуховке, и вам нужно прогреть ее до определенной температуры. Легче всего сделать это с помощью свойства Temperature следуим образом:

class Oven {

private int _temperature;

public int Temperature { get {

return _temperature;

}

set {

_temperature = value;

}

}

}

Класс oven предоставляет температуру, как свойство, которое является прямой ссылкой на переменную „temperature. Код, вызывающий класс oven, периодички запрашивает значение температуры и решает, когда духовка разогрелась до необходимой температуры.

Итак, является ли  класс  oven в  его  текущей  реализации  структурным  классом? На  пользователя  класса  oven возлагается  довольно  значительная  ответственность в том, что он должен периодически запрашивать значение температуры и на основе полученного ответа решать, прогрелась ли духовка до требуемой температуры. Лучшим подходом было бы определить класс, который выполняет эту  работу. Тогда вызывающему коду нужно было бы только спросить у этого класса: "Ты гов?" Такой класс может выглядеть следующим образом:

class Oven {

private int _temperature;

public void SetTemperature(int temperature) {

_temperature = temperature;

}

public bool AreYouPreHeated() {

// Проверяем, соответствует ли температура требуемой. return false;

}

}

Модифицированная   реализация   класса   oven не   предоставляет   члена   данных

_temperature внешнему коду. Также в данной ситуации член данных .temperature не представляет температуру духовки,  но  указывает  верхний  предел  темперуры разогрева. Данный верхний предел устанавливается с помощью метода SetTemperature (). Проверка готовности духовки осуществляется не получением ее температуры, а вызовом метода AreYouPreheated(). Вызывающий код получает ответ в виде значения  true или false, указывающего состояние нагрева духовки.

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

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

Даже с этими аргументами и различием между базовым классом и архитектурным классом уровня рабочей логики некоторые программисты  продолжают  критикать использование свойств. Причиной этому является управление доступом.

Допустим, вы расплачиваетесь за покупки в магазине. Как вы это делаете? Откраете свой бумажник и позволяете кассиру взять из него  необходимую сумму ничными или кредитную карточку? Или наоборот, кладете требуемую сумму в каовый аппарат или сами обрабатываете транзакцию с кредитной карточкой? Ответ на эти вопросы заключается в доверии. Насколько бы не доверяли вы и кассир друг другу, каждый из вас хочет контролировать свою область собственности или ответвенности.

По аналогии с ранее приведенным примером с доступом к разным комнатам и обктам в вашем доме, свойство Temperature можно сравнить с разрешением доста. Например, вы бы не разрешили доступ к своему шкафу любому посетителю, но ваша жена или муж такой доступ имели бы. Любому посетителю вашего дома него делать в вашем шкафу, но своей жене вы, скорее всего, доверяете. Часто стояние и его представление являются вопросом доверия и применения правильной области видимости.

ПРИМЕЧАНИЕ

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

Источник: Гросс  К. С# 2008:  Пер. с англ. — СПб.:  БХВ-Петербург, 2009. — 576 е.:  ил. — (Самоучитель)

По теме:

  • Комментарии