1.Интерфейслар. Интерфейс абстракт классларнинг "чегаравий ҳолати” ҳисобланади. Унда авлод классларда фойдаланиш учун абстракт методлар, ҳусусият ва интексаторлар жамланмаси кўрсатилади. Бошқача айтганда, интерфейслар шу интерфейсдан фойдаланувчи класслар ҳулқини тавсифлайди. ИНтефейслардан фойдаланишнинг асосий мақсади шундай классларга бир ҳил усул билан мурожаат қилиш имкониятини яратишдан иборат.
Хар бир класс интерфейс элементларини ўзича аниқлаши мумкин. Полиморфизм айнан шу усул билан амлга оширилади: турли класс объектлари бир хил методларга турли хил кўринишда жавоб реакциясини кўрсатадилар.
Интерфейс синтаксиси класслар синтаксисига ўхшаш:
[ атрибутлар ] [ спецификаторлар ] interface интерфейс _номи
[ : аждодлари ] Интерфейс_жисми[ ; ]
Интерфейслар учун қуйидаги спецификаторлар кўрсатилиши мумкин: new, public, protected, internal и private.
new спецификатори ички интерфейслар учун қўлланади хамда класс методининг мос модификатори биан бир ҳил маънога эга бўлади. Қолган спецификаторлар интерфейснинг кўринувчанлигини белгилаб беради.
Интерфейс бир нечта интерфейсларнинг ҳусусиятларига ворис бўлиши мумкин. Бу холда авлодлар рўйхати вергуль белгиси орқали кўрсатилади. Интерфейс жисми абстракт методлар, шаблон ва индексаторларнинг ҳусусиятлари, шунингдек ходисаларни ўз ичига олади.
Намуна тариқасида компьютер ўйинлари персонажларининг базавий ҳулқларини белгилаб берувчи IAction интерфейсини кўрамиз. Фараз қилайлик, иҳтиёрий персонаж ўзини экранга чиқариш, ҳужум қилиш ва чиройли ўлишни билиши керак.
interface IAction { void Draw(); int Attack(int a); void Die(); int Power { get; } } IAction интерфейсида учта метод хамда фақат ўқиш учун мўлжалланган Power ҳусусияти аниқланган бўлсин. Агар ҳусусиятларни ўрнатиш имкониятини таъминлаш назарда тутилганда эди, шаблонда хизматчи set сўзини кўрсатиш керак бўлар эди. Масалан:
int Power { get; set; } Интерфейснинг абстракт классдан фарқлари қуйидагича:
Интерфейс элементлари тўғридан – тўғри public очиқлик спецификатори эга бўлади ва шу билан бирга ошкор эълон қилинган спецификаторга эга бўла олмайди;
интерфейс майдон ва оддий методларни ўз ичига ола олмайди —интерфейснинг барча элементлари абстракт бўлиши лозим;
авлодлар рўйхатида интерфейс кўрсатиладиган класс унинг барча элементларини белгилаб бериши лозим, бу вақтнинг ўзида абстракт класснинг авлоди сифатида аждодлариниинг абстракт методларининг бир қисмини қайта аниқлай олмайди;
класс авлодлар рўйхатида бир нечта интерфейсларга эга бўла олмйди ва бунда уларнинг барча методларини аниқлаб бериши лозим.
Интерфейсни амалга оширилиши. Класснинг авлодлари рўйхатида дастлаб унинг базавий класси (ашар у мавжуд бўлса) кўрсатилади, сўнгра вергуль белгисидан кейин бу классни амалга оширувчи интерфейслар ёзилади. Масалан, IAction интерфейсининг Monster классида амалга ошириш жараёни қуйидагича кўринишда бўлиши мумкин:
using System; namespace ConsoleApplication1 { interface IAction { void Draw(); int Attack( int a ); void Die(); int Power { get; } } class Monster : IAction { public void Draw() { Console.WriteLine( "Здесь был " + name ); } public int Attack( int ammo_ ) { ammo -= ammo_; if ( ammo > 0 ) Console.WriteLine( "Ба-бах!" ); else ammo = 0; return ammo; } public void Die() { Console.WriteLine( "Monster " + name + " RIP" ); health = 0; } public int Power { get { return ammo * health; } } …
} Методларнинг интерфейсдаги сигнатуралари хамда амалга оширишлари тўла устма-уст тушиши керак. Интерфейснинг амалга ошириладиган элементларини классда public спецификатори билан кўрсатилади. Бу элементларгакласс объектлари орқали ёки мос типдаги интерфейс объектлари орқали мурожаат қилиш мумкин:
Monster Vasia=new Monster( 50, 50, "Вася" ); / Monster класси объекти Vasia.Draw(); // Натижа: Вася бу ерда бўлган IAction Actor=new Monster( 10, 10, "Маша" ); // интерфейс объектининг типи Actor.Draw(); // Натижа: Маша бу ерда бўлган Интерфейсни классда амалга оширишнинг иккинчи усули ҳам мавжуд: амалга ошириладиган элементдан олдин интерфейс номини ошкор кўрсатиш. Бунда очиқлик спецификатори кўрсатилмайди. Бундай элементларга фақат интерфейс типидаги объектлар орқали мурожаат қил иш мумкин. Масалан:
class Monster : IAction { int IAction.Power { get { return ammo * health; } } void IAction.Draw() { Console.WriteLine( "бу ерда " + name + “бўлган эди”); } ... } ... IAction Actor = new Monster( 10, 10, "Маша" ); Actor.Draw(); // интерфейс типидаги объект орқали мурожаат // Monster Vasia = new Monster( 50, 50, "Вася" ); // Vasia.Draw(); Шундай қилиб, амалга оширилаётган интерфейс номини ошкор эълон қилинганда мос методлар класс интерфейсига кирмайди. Бу ҳолат уни агар интерфейснинг қайсидир элементлари класснинг охирги фойдаланувчисига керак бўлмаганда соддалаштириш имконини беради.
Интерфейс орқали объектлар билан ишлаш. is ва as амаллари.
Интерфейс типидаги объектлар орқали объектлар билан ишлаганада объект мазкур интерфейсни қўллаб – қувватлаштга ишонч ҳосил қилиш зарур. Текшириш бинар is амали ёрдамида бошланади. Бу амал is хизматчи сўзидан чпада турган объектнинг жорий типи ўнг томонда турган тип билан биргаликда эканлигини аниқлайди.
Агар объектни кўрсатилган типга келтириш мумкин бўлса – true, aks xolda – false. Бу амални одатда қуйидаги кўринишда амалга ошириш мумкин:
{ // "объект" ни "тип" га акслантириш // акслантирилган объект билан амаллар бажариш } Фараз қилайлик, биз object типидаги параметрли метод кўринишидаги объект билан қандайдир амал режалаштирган бўлайлик. Бу параметрдан метод ичида ҳосила классларида тавсифланган методларга нисбатан қўллашдан аввал уни ҳосилда классига ўтказиш талаб қилинади. Ўтказишни хавфсиз амалга ошириш учун бунинг иложи борлигини текшириш керак. Бунинг қуйидагича амалга ошириш мумкин:
static void Act( object A ) { if ( A is IAction ) { IAction Actor = (IAction) A; Actor.Draw(); } } Act методига иҳтиёрий объектларни узатиш мумкин, аммо экранга улардан фақат IAction интерфейсини қўллаб – қувватлайдиганларигина чиқарилади.
is амалини қўллашнинг камчилиги шундаки, ўтказиш амалда икки марта бажарилади: текшириш вақтида хамда бевосита ўтказиш вақтида. Унга қараганда самаралироқ амал ҳам мавжуд – бу as амалидир. У берилган типга ўтказади, агар бунинг иложи бўлмаса, null натижасини шакллантиради. Масалан:
static void Act( object A ) { IAction Actor = A as IAction; if ( Actor != null ) Actor.Draw(); } Қараб чиқилган ҳар икки амал интерфейсларга ҳам, классларга нисбатан ҳам қўлланиши мумкин.