Първи стъпки със C# за .Net
Категория: Интернет
10.2.2003
При обектно ориентираното програмиране софтуерните приложения се представят като системи от взаимодействащи си обекти. В процеса на изпълнение на такова приложение биват създавани и инициализирани обекти, чиито характеристики се определят от техните класове. Класът представлява шаблон, по който се създават обекти, дефиниращ типа на данните на тези обекти, операциите, извършвани от тях, и връзките им с други обекти.
В примерен клас, описващ автомобили, бихме дефинирали променливи, които съдържат модела им, годината на производство и техническите им характеристики. Всички обекти от този клас ще притежават едни и същи член-променливи, чиито стойности в отделните обекти могат да се различават. В реалния свят понятието “автомобил” дефинира голяма група от превозни средства със сходна функция и характеристики, но с различаващи се детайли. По подобен начин класовете дефинират програмни конструкции - обекти - със сходна структура и функции.
В C# дефинираме класове посредством ключовата дума class. След нея следват името на класа и тялото му, заградено във фигурни скоби. Тялото на клас се състои от полета, методи и свойства, наречени събирателно членове на класа. Полетата са обикновени променливи, съдържащи данни. Методите, известни и като член-функции, съдържат изпълним код и дефинират операциите, които обектите от класа могат да изпълняват:
using System;
class Vehicle
{
// fields
string producer, model;
int year;
int maxSpeed;
// constructor
public Vehicle(string producer, string model, int year)
{
this.producer = producer;
this.model = model;
this.year = year;
this.maxSpeed = 240;
}
// method
public void DisplayModel()
{
Console.WriteLine(producer + + model +
, + year.ToString());
}
// properties
public int MaxSpeed
{
get { return maxSpeed; } // get the maximal speed
set { maxSpeed = value; } // set the maximal speed
}
public string Model
{
get { return model; } // get model
}
}
class MainClass
{
public static void Main()
{
// create an instance of the Vehicle class
// this executesthe Vehicle constructor
Vehicle v = new Vehicle(Toyota, Avensis, 2000);
// displays Toyota Avensis, 2000
v.DisplayModel();
// displays Max. speed is 240
Console.WriteLine(Max. speed is + v.MaxSpeed);
// set the MaxSpeed property
v.MaxSpeed = 300;
// displays Max. speed is 300
Console.WriteLine(Max. speed is + v.MaxSpeed);
// display the Model property
Console.WriteLine(Model is + v.Model);
}
}
Класът MainClass съдържа входната за приложението функция Main. В нея се създава обект от класа Vehicle. След изпълнението на този ред в променливата v се съдържа указател към новосъздадения обект:
Vehicle v = new Vehicle(Toyota, Avensis, 2000);
Създаване на обект от даден клас води до изпълнението на специален негов метод, наречен конструктор. Конструкторът има същото име като на класа и не връща стойност. Извиква се автоматично, когато обект от класа се създава по време на изпълнение на приложението. В горния пример конструкторът приема 3 параметъра, указващи данни за автомобил - модел и година на производство. Тези стойности се използват в конструктора за инициализация на полетата на обекта:
this.model = model;
Ключовата дума this се използва за обръщение към обекта, за който е извикан метод.
На следващия ред се извиква методът DisplayModel. Метод се извика чрез оператора - точка:
v.DisplayModel();
В C# оператора точка се използва за достъп до членове - данни, методи и свойства. C# поддържа и указатели, подобни на тези в C и C++. Те са достъпни при изпълнение на код в контекст извън предоставяния от .NET средата режим на управление на паметта. Такъв контекст може да се позволи с помощта на ключовата дума unsafe.
Забележете, че всички методи освен конструкторите, трябва да декларират тип на връщаната от тях стойност. Ако метод не връща стойност, той трябва да се декларира с ключовата дума void, както е дефиниран DisplayModel в показания пример.
Счита се за лоша практика да се позволява директен достъп до полетата на обект от даден клас. В C# може да се осъществи контролиран достъп до вътрешните за класа данни чрез т.нар. свойства:
public int MaxSpeed
{
get { return maxSpeed; } // get the maximal speed
set { maxSpeed = value; } // set the maximal speed
}
Свойствата могат да имат get и set методи за достъп. В този пример те съответно връщат или задават стойността на поле от класа. В тялото на set чрез променлива, наречена value, се предоставя достъп до новата стойност, зададена за свойството, например чрез присвояване:
v.MaxSpeed = 300;
Забележете, че методите и свойствата на класа Vehicle се предхождат от ключовата дума public. Тя задава публичен достъп до съответните членове, т.е., ако в даден блок код има достъп до обект от класа, то чрез обекта има достъп и до тези членове на класа. Ако не е зададено изрично дали даден член е достъпен публично, той по подразбиране е private - невидим извън класа. Например следният опит за достъп до поле от класа ще доведе до грешка при компилиране на програмата:
Console.WriteLine(Model is + v.model); // error!
Общоприетият стил е имената на private членовете на клас да започват с малка буква, а имената на другите членове - с главна буква.
Класовете могат да включват статични членове, които могат да се използват, без да е създаден обект от класа. Такива членове се бележат със модификатора static. Следният пример показва декларация на статична променлива:
class Vehicle
{
public static int NumTyres = 4;
...
}
Достъп до полето се осъществява
така:
int numt = Veicle.NumTyres;
Понеже в C# не съществуват глобални променливи, статични полета на клас често се използват за съхранение на глобално достъпни стойности.
Класове могат да съдържат и вложени класове. Тази възможност често се използва при имплементация на класове от тип колекция (поддържащи IEnumerable интерфейса). За тях обикновено се създава и помощен клас, който итерира елементите им. Помощният клас, поддържащ интерфейса IEnumerator, се влага в основния:
using System.Collections;
// the Tokens class contains inner class
public class Tokens : IEnumerable
{
private string[] elements;
Tokens(string source, char[] delimiters)
{
// Parse the string into tokens:
elements = source.Split(delimiters);
}
// IEnumerable Interface Implementation:
// GetEnumerator() method required by IEnumerable
public IEnumerator GetEnumerator()
{
return new TokenEnumerator(this);
}
// inner class implementing IEnumerator
private class TokenEnumerator : IEnumerator
{
private int position = -1;
private Tokens t;
public TokenEnumerator(Tokens t)
{
this.t = t;
}
// declare the MoveNext method required by IEnumerator
public bool MoveNext()
{
if (position < t.elements.Length - 1)
{
position++;
return true;
}
else
{
return false;
}
}
// declare the Reset method required by IEnumerator
public void Reset()
{
position = -1;
}
// declare the Current property required by IEnumerator
public object Current
{
get
{
return t.elements[position];
}
}
}
// Test Tokens, TokenEnumerator
static void Main()
{
// break a string into tokens
Tokens f = new Tokens(A sample sentence to tokenize.,
new char[] { ,-});
foreach (string item in f)
{
Console.WriteLine(item);
}
}
}