Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методичка - Основи Програмування C_.doc
Скачиваний:
46
Добавлен:
18.12.2018
Размер:
1.44 Mб
Скачать

Властивості та індексатори.

1. Властивості.

Властивість (property) – це спеціальний тип членів класу, завдяки якому спрощується реалізація однієї із основних ідей інкапсуляції даних – дані класу мають бути захищені, а методи доступу до них – відкритими. Властивості забезпечують можливість контролю за введенням значень даних-членів класу. Пригадаємо ідею використання закритих членів класу. У наступному прикладі в класі MyClass маємо закрите поле field та пару відкритих методів, які забезпечують можливість зчитування цього поля та запису у нього певної величини з контролем її значення.

using System;

namespace Use_Methods

{

class MyClass

{

private int field; // закрите поле в класі

// відкритий метод для читання поля field

public int get_field()

{ return field; }

// відкритий метод для запису поля field

public void set_field(int value)

{ // якщо запропоноване для поля значення

// додатне, присвоюємо його значенню поля

if (value > 0) field = value;

// інакше встановлюємо значення за замовчуванням

else field = 1;

}

}

class Program

{

static void Main()

{

MyClass m = new MyClass();

Console.WriteLine("Введiть поле");

int i = int.Parse(Console.ReadLine());

//метод записує у поле field значення i, якщо воно додатне

m.set_field(i);

Console.WriteLine("поле = {0}", m.get_field

// як збільшити поле на одиницю?

m.set_field(m.get_field() + 1);

Console.WriteLine("тепер поле збiльшене на 1 : {0}",

m.get_field());

}

}

}

Практично реалізація цієї ідеї означає, що кожне закрите поле повинне бути забезпечене парою відкритих методами для роботи з ними. Але мова С# має більш зручний інструмент – це саме властивості, які були анонсовані вище. Властивість являє собою пару аксесорів (accessor) – get та set, які забезпечують доступ до певного поля класу. Властивість визначається за наступним синтаксисом:

<модифікатор доступу властивості> <тип властивості> <ідентифікатор властивості>

{

get // аксесор get (отримати)

{

// код аксесору get

}

set // аксесор set (встановити)

{

// код аксесору set

}

}

Тут у аксесорі get поміщають код, що повертає значення певного закритого поля класу, з яким пов’язана ця властивість. У аксесорі set визначаються дії, що забезпечують присвоєння тому самому полю певного значення. Причому саме тут можливо передбачити засоби контролю за значенням, яке записується у це поле. Зрозуміло, що <тип властивості> має бути ідентичним типу поля, з яким ця властивість пов’язана. Властивість не має параметрів, звертатись до неї можна просто за ідентифікатором. Важливо розуміти, що коли властивість використовується у лівій частині оператора присвоєння, то автоматично викликається аксесор set, який приймає змінну з наперед визначеним ідентифікатором value. В іншому випадку так само автоматично викликається аксесор get. З технічної точки зору при компіляціїї властивості генеруються два методи, подібні до тих, що ми використали у попередньому прикладі. Слід розуміти, що властивість не має доступу до пам’яті, отже, її використання без деякого поля класу не має сенсу. Властивість лише керує доступом до цього поля. Прийнятий стиль оформлення властивості полягає у використанні для ідентифікатора властивості поля імені, яке збігається із назвою самого поля з точністю до першого символу – у поля це маленька літера, а у властивості цього поля – велика.

Виконаємо таке саме завдання, як і у попередньому прикладі, проте використаємо замість методів доступу до закритого поля field властивість. Тут клас MyPropertyClass має закрите поле field та властивість, що ним керує – Field. Аксесор цієї властивості get просто повертає значення поля field, а аксесор set перевіряє значення змінної value, яка автоматично потрапляє у нього, – якщо це значення додатне, то воно присвоюється полю field, в іншому разі у field встановлюється прийняте за замовчуванням значення 1.

using System;

namespace Use_Properties

{

class MyPropertyClass

{

// закрите поле в класі - ним керуватиме властивість Field

private int field;

public int Field // властивість для поля field

{ get // acsessor get

{ return field; }

set // acsessor set

{ // якщо запропоноване для поля значення додатне,

// присвоюємо його значенню поля

if (value > 0) field = value;

else field = 1;

}

}

}

class Program

{

static void Main()

{

MyPropertyClass mp = new MyPropertyClass();

Console.WriteLine("Введiть поле");

mp.Field = int.Parse(Console.ReadLine());

Console.WriteLine("поле = {0}", mp.Field);

// Як збільшити поле на одиницю? Тепер це простіше!

Console.WriteLine("тепер поле збiльшене на 1 : {0}",

++mp.Field);

}

}

}

Зверніть увагу, коли ідентифікатор властивості фігурує у виразі

mp.Field = int.Parse(Console.ReadLine());

спрацьовує set , який отримує у змінній value (вона цілого типу, бо такого типу сама властивість) значення, введене з клавіатури методом Console.ReadLine(). В інструкції

Console.WriteLine("поле = {0}", mp.Field);

автоматично викликається get, що повертає значення field. Проте в обох випадках звертання до властивості Field виглядає однаково. В той же час, у попередньому прикладі ми звертались до двох різних методів – set_field(i) та get_field(). Крім того, в останньому прикладі для того, щоб збільшити (або зменшити) значення поля field можна використовувати звичайні оператори інкременту (декременту): ++mp.Field чи mp.Field++. Порівняйте, як це відбувалось у прикладі Use_Methods.

В нашому прикладі властивість Field призначена як для читання так і для запису поля field. Проте в деяких випадках властивість може бути використана лише для читання або лише для запису. В такому разі відповідний аксесор просто відсутній. У наступному прикладі властивість Name може бути використана лише для читання значення поля name, адже аксесор set у ній відсутній. При спробі присвоєння цій властивості будь-якого значення виникне синтаксична помилка.

class MyPropertyClass

{

private string name = "MyName";

public string Name // Ця властивість лише для читання

{

get { return name; }

}

}

class Program

{

static void Main()

{

MyPropertyClass mp = new MyPropertyClass();

Console.WriteLine("name = " + mp.Name);

// mp.Name = "NewName"; // тут буде помилка - властивість // лише для читання !

}

}

Основна зручність використання властивостей полягає в тому, що користувач класу звертається до них просто як до звичайних полів класу. З’ясуємо схоже та відмінне між полями (даними-членами) та властивостями класу.

  1. Використовуються поля та властивості с точки зору синтаксису однаково.

  2. Поле розміщується у пам’яті, а властивість – ні.

  3. Властивість є логічним полем, доступ до якого здійснюється через аксесори get та set.

  4. Властивості, як і поля, мають модифікатор доступу.

  5. Властивості, як і поля, можуть бути статичними.

Ознаки схожості властивості проявляють і з методами класу, тому порівняємо і їх.

  1. Властивість, як і метод, містить код.

  2. Властивість, як і метод, приховує деталі свого функціонування.

  3. Властивість, як і метод, може бути статичною.

  4. Властивість, на відміну від методу, не може мати тип void.

  5. Властивість, на відміну від методу, не має дужок із списком параметрів.

  6. Властивість, на відміну від методу, не може перевантажуватись.

Останнє, про що варто нагадати, - формальна змінна value є видимою та може бути використана лише в межах властивості, – звертання до змінної поза властивістю призведе до синтаксичної помилки.