ЭЛЕМЕНТЫ КЛАССОВ. Конструкторы
Основное назначение конструктора – создать объект и элементам данных этого объекта присвоить некоторые начальные значения. Иногда этот процесс называют инициализацией объекта.
Создание объекта является основной задачей конструктора.
Присваивание элементам данных объекта некоторых значений может осуществляться различными способами.
В зависимости от способа определения значений элементов данных объекта различают:
– конструкторы с умолчанием;
– конструкторы с заданием параметров;
– множественные конструкторы.
Конструктор с умолчанием вызывается в программе, без каких либо параметров. Например,
treyg t1 = new treyg();
Это означает, что элементам данных объектаt1 присваиваются некоторые фиксированные значения – обычно нулевые.
Реализация такого конструктора может включать операторы присваивания полям данным класс некоторых фиксированных значений.
Например, в наш класс можно добавить конструктор с умолчанием, который присваивает (по умолчанию) сторонам треугольника фиксированные значения 3, 4 и 5. В этом можно убедиться, если добавить метод печати периметра объекта:
public treyg()
{
a = 3; b = 4; c = 5;
}
public void printO()
{
p = a + b + c;
ss = "Периметр треугольника = " + p.ToString();
}
Рисунок 8.1 – Использование в программе конструктора с фиксированными начальными значениями
Конструкторы с заданием параметров позволяют определять начальные значения элементов данных объекта во время создания объекта.
Объявление таких конструкторов в классе выглядит следующим образом:
public treyg(int sa, int sb, int sc)
{
a = sa; b = sb; c = sc;
}
Многие программисты включают в реализацию конструктора проверку на допустимые значения элементов данных объектов, создавая так называемые «умные» конструкторы. Например, в реализацию конструктора класса треугольник, можно включить следующие проверки элементов данных:
– все стороны треугольника данных должны быть больше 0;
– сумма любых двух сторон треугольника должна быть больше третьей стороны.
Если условия не выполняются необходимо выдать сообщение и присвоить элементам данных объекта некоторые фиксированные значения или повторить ввод.
Объявление такого «умного» конструктора ни чем не отличается от объявления обычного конструктора, а реализация включает все необходимые проверки в функции ввода данных класса, например:
public treyg(int sa, int sb, int sc)
{
vvod(sa,sb,sc);
}
Изменим код программы нашего обработчика события следующим образом – умышленно введем в конструкторе неправильные значения сторон треугольника:
private void button1_Click(object sender, EventArgs e)
{
int A, B, C;
treyg t = new treyg(3,5,9);
t.printO();
A = Convert.ToInt32(textBox1.Text);
B = Convert.ToInt32(textBox2.Text);
C = Convert.ToInt32(textBox3.Text);
t.vvod(A,B,C);
textBox4.Text = t.ss;
}
Работа программы на рисунке 1.6
Рисунок 8.2 – Работа программы с заведомо неправильными значениями в конструкторе
Множественные конструкторы используют перегрузку функций при обработке аргументов разного типа.
Такие конструкторы используются, когда значения данных могут задаваться в различных формах, например, целым или вещественным числами или строкой.
Обычно такие конструкторы применяются для обработки дат.
Используя перегрузку функций можно в описание класса включать несколько конструкторов, «понимающих» данные различного типа.
Например, текущую дату можно задавать по умолчанию или вводить разными способами. Возможны, например, следующие три варианта значений ввода даты:
целыми числами (месяц, день и год – 23 12 07);
некоторым текстом (23 декабря 2007 года);
набором с использованием дополнительных символов (20.10.07 или 17/09/2007).
class date
{
. . .
date() { . . . }
date(int mm, int dd, int gg) { . . . }
date (string tekct) { . . . }
. . .
};
При инициализации объекта возможен любой из предложенных вариантов.
Деструкторы
В языке С# классы могут содержать специальные методы деструкторы.В функциональном плане они должны осуществлять действия, обратные тем, что реализуют конструкторы. Однако особенностью деструкторов языка С# является то, что они не занимаются освобождением памяти, выделяемой конструктором соответствующим объектом (за этим следит сборщик мусора), а освобождают ресурсы, выделенные объекту, например, закрывают связанные с ним файлы, связь с сервером базы данных, связь с другим компьютером и т.д.
Также как у конструктора имя деструктора совпадает с именем класса, но перед именем деструктора устанавливается символ «~» – тильда. Например, если бы наш класс treyg содержал деструктор, то его запись выглядела бы следующим образом:
public ~treyg()
{ тело_деструктора }
Деструктор нельзя вызвать непосредственно в программе — он автоматически вызывается сборщиком мусора при удалении объекта из кучи. Освобождение ресурсов, выделяемых объекту, на практике осуществляется автоматически после того, как надобность в них отпадает, поэтому деструкторы конструктивно присутствуют в структуре класса, но, как правило, не создаются – либо используются по умолчанию.
Свойства
Один из принципов объектно-ориентированного программирования является инкапсуляция. Формально инкапсуляция это объединение полей и методов класса с целью защиты данных от непосредственного доступа из программы. Поля объекта используется через его интерфейс – совокупность правил доступа или свойства. Скрытие полей объекта – их инкапсуляция (от слова «капсула») осуществляется через свойства.
Свойства представляют собой специальныеметоды, которые на самом деле состоят из двух методов – get() и set() инекоторого поля объекта. Метод get() возвращает текущее значение соответствующего поля объекта, а метод set() помещает в поле объекта новое значение. Эти методы вызываются автоматически всякий раз, когда программа хочет получить значение «свойства» или изменить его. С точки зрения синтаксиса свойства ничем не отличаются от полей: они могут стоять в левой части оператора присваивания либо являться членом выражения в его правой части. Например, закрытому полю int a можно записать следующее свойство целого типа Aa.
public class treyg
{
private int a, b, c, p;
public int Aa
{
get { return a;}
set { a = value;}
}
public string ss;
. . .
В программе, после создания объекта t полю a можно присвоить новое значение через свойство Aa следующим образом:
int A, B, C;
treyg t = new treyg();
A = Convert.ToInt32(textBox1.Text);
B = Convert.ToInt32(textBox2.Text);
C = Convert.ToInt32(textBox3.Text);
t.Aa = A;
или переменной программы А присвоить значение поля а объекта t следующим образом:
A = t.Aa;
где t.Aa – это свойство класса treyg.
В приведенном примере свойством t.Аа мы фактически закрытое поле а класса treyg превратили в открытое поле – это можно сделать проще объявив в классе вместо спецификатора private спецификатор public.
Естественно свойства предназначены для реализации более сложной логики доступом к закрытому полю класса. В нашем примере в свойство установки нового значения полю класса мы можем включить проверку значения на условие > 0 и на реализацию только одной попытки записи, например:
set { if (a == 0 && value > 0) a = value;}
Любой из методов доступа свойства (но не оба сразу) может отсутствовать. В этом случае мы получаем свойства, предназначенные только для чтения или только для записи.
Дата добавления: 2018-11-25; просмотров: 267;