Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Пособие КНЕУ.doc
Скачиваний:
24
Добавлен:
07.03.2016
Размер:
3.9 Mб
Скачать

5.3.4. Вихідні параметри

Досить часто виникає необхідність в методах, які формують декілька величин, наприклад, якщо в методі створюються об'єкти або ініціалізуються ресурси. В цьому випадку стає незручним обмеження параметрів-посилань: необхідність надання значення аргументу до виклику методу. Це обмеження знімає специфікатор out. Параметру, що має цей специфікатор, має бути обов'язково привласнене значення усередині методу, компілятор за цим стежить. Зате в коді можна обмежитися описом змінною без ініціалізації.

Змінимо опис другого параметра в лістингу 5.4 так, щоб він став вихідним (лістинг 5.5).

При виклику методу перед відповідним параметром теж указується ключове слово out.

Лістинг 5.5. Вихідні параметри

using System;

namespace ConsoleApplicationl

{

class Class1

{

static void P( int a, out int b )

{

a = 44; b = 33;

Console.WriteLine( "усередині методу {0} {1}", a, b );

}

static void Main( )

{

int a = 2, b;

P( a, out b );

Console.WriteLine( "після виклику {0} {1}", a, b );

}

}

}

Результат роботи цієї програми:

усередині методу 44 33

після виклику 2 33

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

5.4. Ключове слово this

Кожен об'єкт містить свій екземпляр полів класу. Методи знаходяться в пам'яті в єдиному екземплярі і використовуються всіма об'єктами спільно, тому необхідно забезпечити роботу методів нестатичних екземплярів з полями саме того об'єкту, для якого вони були викликані. Для цього в будь-який нестатичний метод автоматично передається прихований параметр this, в якому зберігається посилання на екземпляр, що викликав функцію.

У явному вигляді параметр this застосовується для того, щоб повернути з методу посилання на об'єкт, що викликав, а також для ідентифікації поля у випадку, якщо його ім'я збігається з ім'ям параметра методу, наприклад:

class Demo

{

double у;

public Demo T( ) // метод повертає посилання на екземпляр

{

return this;

}

public void Sety ( double у )

{

this.y = у; // полю у привласнюється значення параметра

}

}

5.5. Конструктори

Конструктор призначений для ініціалізації об'єкту. Він викликається автоматично при створенні об'єкту класу за допомогою операції new. Ім'я конструктора збігається з ім'ям класу. Нижче перераховані властивості конструкторів:

  • Конструктор не повертає значення, навіть типу void.

  • Клас може мати декілька конструкторів з різними параметрами для різних видів ініціалізації.

  • Якщо програміст не вказав жодного конструктора або якісь поля не ініціалізовані, полям значущих типів привласнюється нуль, полям посилальних типів - значення null.

  • Конструктор, що викликається без параметрів, називається конструктором за умовчанням.

До цих пір ми задавали початкові значення полів класу при описі класу (лістинг 5.1). Це зручно у тому випадку, коли для всіх екземплярів класу початкові значення деякого поля однакові. Якщо ж при створенні об'єктів потрібно привласнювати полю різні значення, це слід робити в конструкторі. У лістингу 5.6 в клас Demo доданий конструктор, а поля зроблені закритими (непотрібні в даний момент елементи відсутні). У програмі створюються два об'єкти з різними значеннями полів.

Лістинг 5.6. Клас з конструктором

usingSystem;

namespace ConsoleApplicationl

{

class Demo

{

public int a = 1 ;

public const double с = 1.66;

double y;

public Demo( int a, double y ) // конструктор з параметрами

{

this.a = a;

this.y = y;

}

public double Gety( ) // метод отримання поля у

{

return y;

}

}

class Classl

{

static void Main( )

{

Demoa=newDemo( 300, 0.002); //виклик конструктора

Console.WriteLine (a.Gety( )); // результат: 0,002

Demo b = new Demo(1,5.71 ); // виклик конструктора

Console.WriteLine( b.Gety( ) ); // результат: 5,71

}

}

}

Часто буває зручно задати в класі декілька конструкторів, щоб забезпечити можливість ініціалізації об'єктів різними способами. Приклад:

class Demo

{

public Demo( int a ) // конструктор 1

{

this.a = a;

this.у = 0.002;

}

public Demo( double у ) // конструктор 2

{

this.a = 1;

this.у = у;

}

}

Demo x = new Demo( 300 ); // виклик конструктора 1

Demo у = new Demo( 5.71 ); // виклик конструктора 2

Всі конструктори повинні мати різні сигнатури.

Якщо один з конструкторів виконує які-небудь дії, а інший повинен робити те ж саме плюс ще що-небудь, зручно викликати перший конструктор з другого. Для цього використовується вже відоме вам ключове слово this в іншому контексті, наприклад:

class Demo

{

public Demo( int a ) // конструктор 1

{

this.a = a;

}

public Demo( int a, double у ) : this(a) // виклик конструктора 1

{

this.у = у;

}

}

Конструкція, що знаходиться після двокрапки, називається ініціалізатором, тобто тим кодом, який виконується до початку виконання тіла конструктора.

Як ви пам'ятаєте, всі класи в С# мають загального предка - клас object. Конструктор будь-якого класу, якщо не вказаний ініціалізатор, автоматично викликає конструктор свого предка. Це можна зробити і явним чином за допомогою ключового слова base, що позначає конструктор базового класу. Таким чином, перший конструктор з попереднього прикладу можна записати і так:

public Demo( int а ) : base( ) // конструктор 1

{

this.а = а;

}

Конструктор базового класу викликається явним чином в тих випадках, коли йому потрібно передати параметри.

До цих пір мова йшла про “звичайні ” конструктори, або конструктори екземпляра. Існує другий тип конструкторів - статичні конструктори, або конструктори класу. Конструктор екземпляра ініціалізував дані екземпляра, конструктор класу - дані класу.

У класі, що складається тільки із статичних елементів (полів і констант), описувати статичний конструктор не обов'язково, початкові значення полів зручніше задати при їх описі.

В лістингу 5.7 приведений приклад статичного класу.

Лістинг 5.7. Статичний клас

using System;

namespace ConsoleApplicationl

{

static class D

{

static int a = 200;

static double b = 0.002;

public static void Print ( )

{

Console.WriteLine("a="+a);

Console.WriteLine("b="+b);

}

}

class Classl

{

static void Main( )

{

D.Print( );

}

}

}

Як приклад, на якому демонструватиметься робота різними елементами класу, створимо клас Monster, моделюючий персонаж комп'ютерної гри. Для цього потрібно задати його властивості (наприклад, кількість щупальців, силу або наявність гранатомета) і поведінку. Опис класу Monster приводиться на лістингу 5.8.

Лістинг 5.8. Клас Monster

using System;

namespace ConsoleApplication1

{

class Monster

{

public Monster( )

{

this.name = "Noname";

this.health = 100;

this.ammo = 100;

}

public Monster(string name) : this( )

{

this.name = name;

}

public Monster( int health, int ammo, string name )

{

this.name = name;

this.health = health;

this.ammo = ammo;

}

public string GetName( )

{

return name;

}

public int GetHealth( )

{

return health;

}

public int GetAmmo( )

{

return ammo;

}

public void Passport( )

{

Console.WriteLine( "Monster {0} \t health = {1} ammo = {2}",

name, health, ammo );

}

string name; // закриті поля

int health, ammo;

}

class Classl

{

static void Main()

{

Monster X = new Monster( );

X.Passport( );

Monster Vasia = new Monster("Vasia");

Vasia.Passport( );

Monster Masha = new Monster(200, 200, "Masha" );

Masha.Passport( );

}

}

}

Результат роботи програми:

Monster Noname health = 100 ammo = 100

Monster Vasia health = 100 ammo = 100

Monster Masha health = 200 ammo = 200

У класі три закриті поля (name, health і ammo), чотири методи (Getname, Gethealth, Getammo і Passport) і три конструктори.