C# вундеркіндам. Частина 2. Вчимося спілкуватися з комп'ютером. Переклад частини 2 книги "C# для вундеркиндов": http://msdn.microsoft.com/ru-ru/library/bb330920(v=vs.80).aspx
Коротко в попередній серії частині
Діалог молодих людей. Звучить пропозиція негайно програмувати та застереження, що для цього слід довго і нудно навчатися. Програмування без належних знань уподібнюється їзді на велосипеді наосліп. Проте програмувати на C# слід з насолодою.
Далі йде опис пакету для розробки програм на C# на основі Microsoft Visual C # Express Edition. Створення консольного додатку та написання найпростішої програми.
Також пояснюється компіляція програми, запуск на виконання, доповнення коментарями. Завершується перша частина пропозицією налагодити спілкування з комп'ютером.
Основні труднощі при написанні комп'ютерних програм полягають в тому, що комп'ютер і ми «виховані» різними батьками. Якби це було не так, то ми досягли б єдиного розуміння навколишнього світу і навчилися б говорити спільною мовою. Таким чином нам було б легше розуміти один одного. Ми могли б просто попросити комп'ютер намалювати кота і все. Ви скажете: «Так давайте навчимо комп'ютер розуміти нас!». Але комп'ютери влаштовані зовсім не так як людський мозок і«бачать» світ зовсім по-іншому, тому навчити їх мислення схожого до нашого ― непросте завдання.
Вирішенням може стати пошук компромісу:
єдиний «погляд на світ» і
спільна мова, яку здатні розуміти як люди, так і комп'ютери.
Ця частина книги повністю присвячена вивченню способів спілкування з комп'ютером. Буде потрібно дещо «розвернути» свою свідомість, щоб побачити речі з позиції комп'ютера. При цьому доведеться піти на взаємні поступки: комп'ютер зможе навчитися багато чому (наприклад дізнається деякі слова) з нашого світу, але й ви повинні будите вивчити дещо зі світу комп'ютерів. Спробуйте забратися в «голову» комп'ютера і уявити, як можна було б викласти думки.
Комп'ютери не можуть здогадуватися про те, що ми думаємо, чого від них хочемо і яким чином вони можуть виконати наші бажання. Ми можемо тільки мріяти про той день, коли комп'ютери почнуть розуміти нас з одного погляду в їхній бік і руху брів, але зараз, в реальному світі, нам доводиться чітко викладати свої ідеї і навіть давати комп'ютерів вказівки, яким вони зобов'язані слідувати, щоб допомогти нам. Коротше кажучи, між людьми і машинами існує велике взаємне нерозуміння, і якщо ми хочемо домогтися від них допомоги, нам доведеться його подолати.
Отже, давайте ненадовго забудемо про комп'ютери та уявімо, що вам вкрай необхідно організувати спілкування з якимсь прибульцем. А історія така ...
На щастя чи ні, але щось сталося у Всесвіті і богзна як це сталося, але ви й дивний прибулець опинилися на маленькому, пустельному острові посеред океану. Після запеклого «Привіт, мене звати Світлана, а тебе?», Ви, врешті-решт, вирішуєтедати своєму супутнику ім'я Алджі.
Дає про себе знати голод і ви помічаєте кілька кокосів, що ростуть на високій пальмі, дістати які міг би Алджі, але його допомоги не варто й чекати, якщо не вдасться знайти взаєморозуміння.
На піску ви малюєте зображення кокосової пальми і, вказуючи на нього, вимовляєте слово «ко-кос». Вас вражає те, що Алджі моментально реагує на слово «ко-кос». Ви малюєте інші зображення і Алджі чудово на них реагує. Виявляється, що у цього створіння талант до мов. До настання сутінок Алджі опановує українською.
Будучи схвильованою власним успіхом, ви дивитеся Алджі в очі. «Алджі, будь ласка, підніми мене на плечі, щоб я могла дістати кокоси».
Він дивиться на вас спантеличено. Потім з таким же видом дивиться на зображення кокосової пальми. Потім знову на вас. Ізнову на малюнок. Марно - він не розуміє! Усвідомивши свою помилку, ви хапаєтеся за голову і розгублено показуєте насправжню пальму. Але Алджі як і раніше не може зрозуміти. Виявляється, він розуміє тільки по малюнках. Ага! Вам поступово стає ясно, що хоча Алджі і може називати предмети своєю мовою, він, фактично, НЕ розуміє реальних речей, про які ви говорите.
Якимось чином необхідно прийти до спільного погляду на світ. Ви думаєте, що все просто: раз вдалося навчити його мови,то можна також навчити розуміти об'єкти реального світу. Але й через три доби кокоси і раніше залишаються на пальмі. Уроки проходять не дуже добре і ви втрачаєте контроль у міру того як розуміння вислизає від вас.
Ви не знаєте, сон це, галюцинації або бачення, але фігура в білому з'являється в яскравому, туманному світлі. Низький голос підказує вам: «Ось чудовий спосіб сприйняття навколишнього світу!». «Цим способом ви і Зніфф12 зможете домогтися розуміння». (Ви здогадуєтеся, що "Зніфф12" – справжнє ім'я Алджі.) Ви втрачаєте почуття часу в міру того, як образи магічно потрапляють у ваш розум, навчаючи новому способу опису світу. Нарешті заспокоївшись, вам вдається вийти з цього безтурботного стану.
Стрепенувшись, ви хапаєте Алджі за плечі: «Я все зрозуміла, приятель, слухай уважно те, що я тобі скажу». Алджі з насупленим виглядом вслухається в ваші слова.
Тепер, повернемося до задачі вираження своїх думок таким чином, щоб комп'ютер зміг зрозуміти те, що ми намагаємося сказати.
У C # опис класу для комп'ютера може мати наступний вигляд:
class Animal
{
}
З цього невеликого уривка коду комп'ютер тепер розуміє, що
ми збираємося обговорювати клас об'єктів
ми назвемо цей клас Animal
все опис цього класу буде розташовано між фігурними дужками {...}.
У той час як ім'я класу «Animal» безумовно буде мати сенс у програмі, що виводить на екран зображення тварин або зберігає цікаві факти про них, також можливі такі класи як «MyPhotoProgram» або «MyGradeCalculator». Отже потрібно розуміти, що класи зовсім не обов'язково працюють з об'єктами, що існують в реальному світі - ім'я класу дається для опису того, з чим він має справу.
Комп'ютеру відомо слово «class», яке має бути написано малими літерами, але ім'я класу може бути будь-яким і містити як прописні, так і малі літери. Використання проміжків (пробілів між словами) не допускається.
Для спрощення читання й розуміння код слід писати на окремих рядках, але для комп'ютера немає принципової різниці.Наприклад, код може виглядати наступним чином:
Розглянемо інший приклад: групу всіх живих організмів можна об'єднати в два класи - «рослини» і «тварини».
«У навколишньому світі існують різні класи об'єктів – рослини, тварини, голодні люди, інопланетяни і так далі».
«Зараз я хотіла б розповісти тобі про існуючі об'єкти на цьому острові. А саме, якщо ти не помітив, мене дуже цікавить ця кокосова пальма (яка, між іншим входить в клас званий «рослинами»). Мені також цікавий он той слон. Ух ти! Дивно, як це я не побачила його раніше ». (Ви вказуєте на кожен об'єкт, про який говорите).
«Слон входить в клас, названий «тваринами» і має деякі важливі для нас властивості, Алджі. По-перше, всі тварини можуть рухатися. По-друге, слон по-справжньому важкий. Напевно, тонни дві і це нам знадобиться. По-третє, у нього поганий характер, що теж може виявитися корисним.
«Ну добре, Алджі, тепер слухай мене ... «У навколишньому світі безперервно відбуваються події. Я зголодніла - це подія. Кокоси дозрівають - це подія. Іноді ми самі можемо викликати події, щоб виконати деяку дію. У мене є прекрасна думка, давай викличемо подію «занепокоєння слона», це змусить його допомогти нам виконати дію «добування кокосів».
«Давай розділимо обов'язки. Я викличу подію (відверну увагу слона на тебе), а ти змусиш його дістати для нас кокоси, домовилися?» При цьому Алджі боязко дивиться на вас і визнає: «Свєта, я чую твої слова, але не знаю як це зробити». Поплескуючи товариша по спині, ви говорите: «Алджі, не турбуйся, я ніколи не стану просити тебе про що-небудь, спочатку не пояснивши тобі метод виконання цієї дії». Ось що потрібно буде зробити після того, як я відверну слона і скажу тобі «діставати кокоси»:
Вибігай з-за цього каменю і вставай поруч з пальмою. Слон негайно понесеться до тебе.
У той момент, коли він досягне намальованої мною на піску лінії, біжи з усіх сил (повертай в різні сторони, тому що бігати туди-сюди - не найкраща думка).
Він вдариться об пальму і на деякий час оцепеніє, але силою удару кокоси будуть збиті і ми пізніше зможемо зібрати їх.
Після цього повертайся у вихідну точку і повідом результат.
Алджі надовго завмирає, очевидно переварюючи завдання, перш ніж несподівано дістає супердосконалий пристрій зв'язку. Протягом деякого часу він передає модемні звуки в цей пристрій і потім знову кладе його в кишеню. Ви питаєте: «Що все це було, Алджі?». Алджі відповідає: «Дозволь мені перекласти, Світла ...
Існує клас об'єктів, званих Ікс-зніфферами.
Я один з об'єктів такого класу, але є й інші.
Всі об'єкти цього класу мають такі властивості:
- Name (наприклад моє ім'я - Зніфф12)
- EarShape (ФормаВуха) (значення якого завжди «трубка»)
- LikeToWatchTV (ЛюблюДивитисяТелевізор) (у більшості випадків має значення істини, а в інших випадках - брехні)
Повинен зізнатися, що моя поява тут не випадково. Ти потрапила на популярне ТВ-шоу «Залишитися в живих». Але я тільки що подзвонив своєму продюсеру і сказав, що мене не задовольняє обіцяна плата за таке завдання. Він збирається негайно виконати метод "НадіслатиРятувальнуГрупу".
На цьому казкова історія закінчується. Сенс в тому, що вам з Алджі вдалося розробити загальний спосіб опису світу - ви використовуєте одні і ті ж терміни і однаково розумієте їх значення. Це, поряд з використанням єдиної мови, надає можливість спілкування.
Тепер уявімо, що замість інопланетянина, вам потрібно порозумітися з комп'ютером. Рішення буде аналогічним, як і в розказаної історії. І проблему можна буде вирішити подібним чином: погодивши певний загальний спосіб погляду на світ, який зможе забезпечувати як розуміння людиною, так і машиною.
Підхід з використанням «класів, об'єктів, властивостей, подій і методів», про який було розказано в історії, не є бездоганним. Це тільки один із способів, який можна вибрати для пояснення навколишнього нас світу прибульцеві. Важливо те, щоб ви обидва домовилися про опис світу єдиним чином. Такий погляд на світ, який, між іншим, називається «об'єктно-орієнтованим» підходом, став дуже популярним способом опису речей комп'ютерів, і фактично, мова C # вимагає дотримуватися саме його.
Отже, вивчення мови C # це вивчення способів опису речей за допомогою класів, об'єктів, подій, методів і т.д.
Якщо ви хочете, щоб комп'ютер допоміг у виконанні необхідних вам дій, то:
Вам (як людині) потрібно вивчити мову C # і навчитися описувати речі з орієнтацією на об'єкти.
Вам необхідно встановити додаток C # та інші супутні програми. Тепер і комп'ютер зможе розуміти мову C # і зможе працювати з об'єктами, описаними у відповідності з об'єктно-орієнтованим підходом.
Ось і все! Ви з комп'ютером маєте спільне уявлення світу, а також мову, і незабаром будете спілкуватися як старі приятелі.
Дозвольте тепер описати значення орієнтації на об'єкти з точки зору програміста.
Навколишній нас світ можна розділити на різні класи речей, такі як «коти» або «будинки» або «дерева». Такі класи можна вважати категоріями або мітками для угруповання подібних об'єктів. Завдання полягає в пошуку способу опису таких класів для комп'ютера, щоб він міг виконувати з ними дії.
Кожен клас речей включає певні об'єкти, які й потрібні нам. Наприклад, до класу «кіт» входить мій кіт Пушок, який є об'єктом класу котів. Подібним чином, рожевий будинок на розі моєї вулиці є об'єктом класу «будинок», а дуб, що видно з вікна моєї спальні, є об'єктом класу «дерево». Якщо є певний об'єкт, з яким повинен працювати комп'ютер, то нам необхідно створити деякий опис для комп'ютера, яке представляє такий об'єкт.
Для об'єктів характерні різні властивості. Властивості служать для більш чіткого опису об'єктів. Їх можна порівняти з прикметниками в українській мові. Наприклад, мого Пушка можна описати такими властивостями як зріст, вага та іншими.
Події - це зміни, що відбуваються з об'єктом. У реальному світі події відбуваються навколо нас безперервно. Наприклад, коли я гладжу Пушка, ця подія відбувається з ним. Подібним чином, вітер, що розвіває гілки дуба, якого видно з мого вікна - це подія, що відбувається з деревом. Події, як правило, являють собою дії, що впливають на певний об'єкт, але сам об'єкт вплинути на них не може. У комп'ютерному світі подіями можуть бути «натискання кнопки» або «переміщення миші».
Дії виконуються об'єктом. Наприклад, кіт Пушок лиже свою шерсть - це дія. У комп'ютерному світі, іноді, коли відбуваються цікаві події, ми хочемо, щоб виконувалися певні дії, наприклад «малювання зображення кота при натисканні на кнопку».
Хочете вірте, хочете ні, але комп'ютери по-справжньому нерозумні. Комп'ютер не має уявлення про те, як намалювати кота.Тому необхідно дати опис, який буде зрозумілим комп'ютеру - метод малювання кота. Метод являє собою набір покрокових інструкцій, які визначають порядок малювання кота, подібно до рецепта.
У наступних розділах ми розглянемо кожен аспект об'єктно-орієнтованого програмування і наведемо більш детальний опис. Ми також детально вивчимо як програмувати на мові C #.
Навколишній нас світ можна розділити на різні групи речей. Назвемо їх класами.
В якості одного з явних прикладів розглянемо класи в школі. Дітей певного віку або з певними здібностями можна об'єднати в групу і назвати її класом. Це дозволить вирівняти дітей. Всі вони будуть навчатися приблизно однаково і здавати одні іспити.
Але це не означає, що всі учні класу однакові, а лише говорить про те, що у них є певні спільні риси.
Будівельний блок: Класи
Усі програми на мові C # створюються всередині класів. Основна структура класу для комп'ютера має наступнийвигляд:
class Animal
{
}
class Animal { }
На попередньому уроці ви дізналися як завести розмову з комп'ютером про клас тварин загалом, але, можливо, в якийсь момент часу ви захочете розповісти щось про один чи кілька визначених об'єктах. Наприклад, що «є певна істота в класі тварин, яку ви називаєте Барсиком».
Це можна виразити таким чином:
Animal Barsik;
Ми написали невеликий уривок коду, і тут потрібно зупинитися щоб подумати, інакше можна втратити головну думку.Комп'ютер розуміє таке: «Ця людина хоче поговорити про об'єкт у класі «Animal» і назвати його «Barsik». Я не знаю, що таке Barsik, але якщо людина хоче це так називати, то мені все одно».
Однак нам потрібно доповнити наведений вище код ще одним виразом:
Barsik = new Animal ();
Може здатися дивним, чому потрібно зробити саме так. Але з точки зору комп'ютера в цьому є сенс. Подумайте як машина і уявіть таке:
Перший вираз попереджає комп'ютер, що незабаром ми попросимо його працювати з певним індивідуумом в класі «Animal». Тепер у комп'ютера з'являється можливість перевірити свої знання про цей клас. Він переглядає всю програму і шукає опис класу з ім'ям «Animal». Якщо він не знаходить такого об'єкта, то може попередити вас: «Ей, я не зможу цього зробити!». Якщо ж вдається знайти потрібне опис, він просто продовжить виконання програми, взявши до уваги, що ви пізніше попросите його виконати деяку дію з об'єктом класу «Animal» на ім'я Barsik.
Трохи пізніше ми додамо другий вираз, яке скаже комп'ютера: «Гей, пам'ятаєш об'єкт Barsik? Тепер мені потрібно виконати з ним дію. Звільни простір в голові для роздумів про цю тварину. Комп'ютер представляє новий об'єкт «Animal» в своїй голові і розуміє, що ви говорите про той же об'єкті (Barsik), згаданий раніше. Вивчивши клас «Animal», комп'ютеру стало дещо відомо про Барсика, і він тримає цю інформацію напоготові у своїй голові в надії на те, що отримає від вас додаткові дані або кілька запитань щодо Барсика.
Тепер давайте розглянемо всі три моменти і представимо як комп'ютер «думає» про них
Трохи пізніше ми розповімо про те, що відбувається всередині опису класу (між фігурними дужками). Але спочатку ми обговоримо об'єкти.
Кожен клас містить ряд реальних об'єктів. Наприклад, у класі об'єктів «Animal» можуть бути присутніми певні істоти:
Сусідський кіт «Барсик»
Корова, побачена вами одного разу, прізвисько якої вам невідомо.
Горила на прізвисько Джеремі.
та інші об'єкти.
Зауважте, у першому блоці ми описуємо клас об'єктів загалом, а в блоках 2 і 3 ми виділили певний об'єкт в класі Animal.
Будівельний блок: Об'єкти
Об'єкти - це певні окремі елементи деякого класу.
Клас просто описує «на що схожі ці об'єкти» загалом. Такий основний план створення об'єкта.
class Animal
{
}
Якщо планується працювати з певним об'єктом, необхідно завчасно повідомити комп'ютер, до якого класу він належить, так щоб спочатку комп'ютер
перевірив свої знання про цей клас. Для цього ми вказуємо ім'я класу, а потім даємо об'єкту ім'я на вибір.
Ім’я класу
Animal (укр. Тварина)
Ім’я объекту
percyThePorcupine; (укр. персіДикобраз)
Цей процес називається «оголошенням об'єкту».
Коли ж ми будемо готові працювати з цим об'єктом, ми повинні попросити комп'ютер «створити екземпляр» класу. Тепер на основі своїх знань про клас комп'ютер створює реальний об'єкт, з яким він зможе виконувати дії.
percyThePorcupine = new Animal ();
У цьому прикладі «percyThePorcupine» тепер є екземпляром «Animal» або можна сказати, що percyThePorcupine це «об'єкт» типу «Animal». Але в будь-якому разі тепер нам точно відомо, що ми говоримо про певний об'єкт класу «Animal». Це називається «створенням об'єкта».
Тепер ми знаємо, як розповісти про певний об'єкт в класі, але оскільки клас, що визначається нами досить простий (ну так, згоден, він повністю порожній), то з ним зовсім нецікаво працювати. Отже, на наступному уроці ми додамо деякі елементи до нашого класу.
Якби я попросив вас перерахувати кілька властивостей тварин, то швидше за все список був би таким:
Вид тварини (Kind of animal)
Зріст (Height)
Довжина (Length)
Кількість лап (Number of legs)
Забарвлення (Color)
Наявність хвоста (Has a tail)
Ссавець (Is a mammal)
При розгляді властивостей цих тварин ви можете присвоїти значення кожної з них
Kind of animal = «Cat»
Height = 50 cm (великий котяра!)
Length = 110 cm
Number of legs = 4
Color = «Black»
Has tail = true
Is mammal = true
У C # ці властивості зазвичай називаються полями. (Слово «властивості» використовується з дещо іншою метою, і тут ми не будемо вдаватися до деталей).
Тепер розглянемо дещо, про що в реальному світі не доводиться особливо турбуватися, але для комп'ютерів це має величезне значення: Незважаючи на те, що всі зазначені вище властивості здаються однорідними, фактично існують різні типи полів. Наведемо кілька прикладів.
Значення полів height, width і number of legs є числами. Як правило, нам необхідно, щоб комп'ютер використовував ці значення для виконання математичних операцій. Так відбувається в більшості випадків.
Ці поля можна було б назвати так: «numberOfBananas», «numberOfPeople» і «numberEachOneGets». Вони повинні мати числовий тип, оскільки нам необхідно виконати з ними якийсь розрахунок за допомогою математичного поділу.
Примітка. У мові C #, імена полів не можуть містити проміжки (пробіли). Використовуйте прості символи, такі як букви і числа.
Значення полів kind of animal і color складатися з букв, скріплених разом - в цьому випадку літери складають слова «cat» і «black».
При цьому варто відзначити, що і рядкові поля можуть також містити числа. Наприклад, рядкове поле може містити наступний текст: «Сьогодні це вже 17 крокодил, якого я бачу!». У цьому рядку присутні букви алфавіту, пробіли, числа та знаки пунктуації. Але зчислами в рядку не можна виконувати математичні операції.
Поле типу has tail завжди буде приймати значення ІСТИНА або БРЕХНЯ (true / false), також як і будь-які поля типу ТАК чи НІ («yes / no»).
Кожен «тип» обробляється комп'ютером по-різному, тому при визначенні полів ми повинні вказувати їх тип. В одній програмі ми можемо визначити обробку поля number of legs як рядки з літерами, оскільки нас не цікавлять математичні операції з цією властивістю, тоді як в іншій програмі може знадобитися використання такого поля як числового, так як нам знадобиться дізнатися скільки кінцівок у 500 таких об'єктів.
Тип «String» (рядок)
Щоб повідомити комп'ютера, що якусь властивість потрібно розглядати як рядок літер, необхідно просто доповнити код наступним чином:
string kindOfAnimal;
Поки ми не вказуємо значення в цьому полі, а просто повідомляємо комп'ютера з яким типом даних будемо працювати і присвоюємо полю ім'я. Поставте себе на місце комп'ютера і уявіть як би ви відреагували, якби людина написала для вас таке.
Числові типи
Щоб повідомити комп'ютера, що значення поля потрібно розглядати як число, необхідно вибрати один з декількох числових типів, відомих в мові C#. Найбільш поширений з них - integer. З курсу математики ви повинні знати, що це не що інше як ціле число, яке може бути негативним, позитивним чи нулем.
Простий спосіб дати комп'ютеру зрозуміти, що значення поля повинно бути цілим числом, наступний:
int numberOfLegs;
А так буде думати наш цифровий друг ...
Отже, поля є елементи даних, що дозволяють краще описати об'єкти в класі. Вони завжди мають певний тип.
Додавання полів у клас
Раніше, коли ми повідомили комп'ютер про клас тварин, ми просто назвали клас «Animal», включили в код фігурні дужки і пообіцяли, що пізніше розповімо про нього більше, а точніше про те, що знаходиться всередині нього:
class Animal
{
...
}
Ну що ж, тепер ми готові до цього. Давайте додамо кілька полів у визначення класу.
class Animal
{
string kindOfAnimal;
string name;
int numberOfLegs;
int height;
int length;
string color;
bool hasTail;
bool isMammal;
bool spellingCorrect;
}
(Щоб код був акуратним і легко читався, зазвичай створюються відступи полів, як показано вище. Для цього використовуйте клавішу TAB на клавіатурі. Можна також виділити кілька рядків і відразу створити відступи за допомогою клавіші TAB.)
Використання полів з певними об'єктами
Отже, тепер ми пояснили комп'ютеру, що ВСІ об'єкти класу «Animal» мають ці поля. Тепер давайте попросимо комп'ютер створити екземпляр, який являє певний об'єкт класу «Animal» (як ми робили це в попередньому розділі) і повідомимо комп'ютеру деяку інформацію про цей певний об'єкт, присвоївши значення кожному полю.
Animal Barsik;
Barsik = new Animal ();
Barsik.kindOfAnimal = "Cat";
Barsik.name = "Кіт Барсик";
Barsik.numberOfLegs = 4;
Barsik.height = 50;
Barsik.length = 110;
Barsik.color = "Black";
Barsik.hasTail = true;
Barsik.isMammal = true;
Зверніть увагу, що значення рядкових полів завжди береться в лапки (""), але тільки не значення інших типів полів. В кінці кожного виразу ставиться крапка з комою (;).
На даному етапі варто згадати, що вибране нами ім'я об'єкта «Barsik» не несе ніякого емоційного значення для комп'ютера. Він би також легко працював з об'єктом, якби ми замінили всі імена «Barsik» на «X» чи будь-яке інше ім'я на вибір:
Animal X;
X = new Animal ();
X.kindOfAnimal = "Cat";
X.height = 50;
X.length = 110;
X.color = "Black";
X.hasTail = true;
X.isMammal = true;
Хоча поля можуть розташовуватися на краю сторінки, вважається доброю звичкою дотримуватися відступів за допомогою табуляції від правого краю, які можна створити за допомогою клавіші TAB на клавіатурі. Це спрощує читання коду.
Поля завжди мають певний тип. Існує багато різних допустимих типів, ось опис деяких найбільш поширених з них:
Тип «Boolean» (логічне значення)
Якщо вам відомо, що деяке поле буде завжди приймати значення «true» або «false» і нічого крім цих значень, то використання поля типу «true / false» в C # може виявитися корисним. У такого типу поля досить дивна назва (Boolean) на ім'я математика Джорджа Буля, але насправді це найпростіший з усіх типів.
Щоб повідомити комп'ютера, що поле «hasTail» має приймати значення «true / false», використовуйте наступний код:
bool hasTail;
Машина буде думати так.
Будівельний блок: Поля
Зазвичай в класі є одне або кілька полів, які дозволяють описувати певні риситакого класу
class SchoolKid
{
string firstName;
string lastname;
int age;
bool isWideAwake;
}
Зверніть увагу на різні рівні захищеності дітей в сім'ї, як показано на малюнку вище. Малютка Світлана закрита (private) в кімнаті - її не випускають з будинку і вона має найбільш високий рівень захисту. З нею можуть спілкуватися люди, що володіють найбільшою довірою. Борис може знаходитися як на передньому, так і задньому дворі, але він як і раніше в певною мірою захищений (protected). Толя, старша дитина, є відкритим (public) для інших і будь-хто може спілкуватися з ним.
Отже, на початок оголошення поля ми можемо додати наступне слово:
class Animal
{
public string kindOfAnimal;
public string name;
public int numberOfLegs;
public int height;
public int length;
public string color;
bool hasTail;
protected bool isMammal;
private bool spellingCorrect;
}
Ви може поцікавитися, а що якщо ми не станемо включати ці слова. У цьому випадку комп'ютер мовчки сприймає код, як якщо б на початку оголошення було написано слово «private», оскільки «private» задається за замовчуванням. Тому поле hasTail автоматично стає закритим (private).
Що означають ці слова?
Private означає, що «об'єкти тільки цього класу можуть звертатися до даного поля»
Public означає, що «об'єкти будь-якого класу можуть звертатися до цього поля»
Protected означає, що «тільки об'єкти тісно пов'язаних класів можуть звертатися до поля»
Наступні приклади двох класів демонструють описаний принцип полів public і private. Ми не станемо далі обговорювати поля типу protected. Додаткові відомості про них можна отримати в довідці Visual C # Express.
Як і раніше, ми спочатку визначаємо кілька закритих і відкритих полів у класі «Animal» і потім намагаємося звернутися до них з класу «Zoo».
class Animal
{
public string kindOfAnimal;
public string name;
public int numberOfLegs;
public int height;
public int length;
public string color;
bool hasTail;
protected bool isMammal;
private bool spellingCorrect;
}
class Zoo
{
Animal a = new Animal ();
/ / Наступний рядок буде виконана успішно, оскільки класу «Zoo» дозволено
/ / звертатися до відкритих полів у класі «Animal»
a.kindOfAnimal = "Kangaroo";
/ / Обидві наступні рядки НЕ будуть виконані, оскільки класу «Zoo»
/ / Не дозволено звертатися до закритих або захищеним полям
a.isMammal = false; / / Спроба звернення до захищеного методу
a.spellingCorrect = true; / / Спроба звернення до закритого методу
}
Програми були б досить малокорисними, якби дозволяли тільки описувати об'єкти. Безумовно, ми хочемо, щоб вони крім іншого виконували деякі дії.
Виводили слова на екран
Вирішували завдання
Копіювали дані з веб-сайту
Регулювали яскравість фотографії
... І могли виконувати ще тисячі операцій
А тепер згадайте уроки, на яких вас вчили додаванню чисел. Скоріш за все, спочатку вас учили тому ЯК додавати числа, можливо, покроково описуючи порядок дій. Іншими словами, в першу чергу вас вчили МЕТОДУ вирішення подібного типу завдання. Метод являє собою набір покрокових інструкцій, що пояснюють порядок виконання дій.
При визначенні поля в програмі необхідно вказати його тип та ім'я:
string lastname;
Позначення типу повинно бути відоме комп'ютеру. Зазначені вище основні типи (як int) пишуться малими літерами, проте деякі типи можуть містити великі літери.
Іменем поля може бути будь-яке слово, наприклад «ZavzdiNapogotovi» з поєднанням великих і малих літер. Використання пропусків (пробілів) не допускається.
При роботі з певним об'єктом, полям зазвичай присвоюються значення, які допомагають описувати об'єкт. Якщо, наприклад, у нас є об'єкт з ім'ям schoolKid, то його полям можна було б присвоїти наступні значення:
schoolKid.firstName = "Jiminy";
schoolKid.age = 13;
Назва об'єкту та ім'я поля розділяються крапкою (.).
Отже, schoolKid.firstName = "Jiminy" означає «значення "Jiminy" підставити в поле firstName об'єкта schoolKid».
Закриті, захищені і відкриті поля
При першому вивченні мови C # цей розділ не буде настільки важливим, але надалі вам можуть зустрічатися слова «private», «protected» і «public» і ви захочете дізнатися їх значення. Давайте обговоримо це питання.
class Animal
{
string kindOfAnimal;
string name;
int numberOfLegs;
int height;
int length;
string color;
bool hasTail;
bool isMammal;
bool spellingCorrect;
}
class MyTestClass
{
}
Об'єкти можна брати з одного класу, такого як MyTestClass вище, і говорити про об'єкти в іншому класі, такому як Animal.
При оголошенні полів так, як це показано вище, ми можемо вирішити, чи повинні інші класи мати доступ до них чи ні. Іноді дуже важливо робити поля закритими (private), наприклад тому що інший клас може поміщати неправильні значення в поля і порушувати роботу програми. Використання полів «private», «protected» і «public» визначає наскільки безпечним буде наш клас.
Тепер, коли вам відомий метод вирішення завдань певного типу, ви зможете вирішити будь-які поставлені перед вами завдання, дотримуючись його.
Подібним чином, щоб комп'ютер виконував потрібні нам дії, ми повинні написати код, що роз'яснює порядок їх виконання, іншими словами, ми повинні описати метод, який буде використовуватися для виконання необхідних дій. Потім цей метод можна буде застосовувати кожен раз при вирішенні завдання подібного типу.
У мові C # метод представлений уривком коду з описом порядку виконання певних дій. Коли згодом ми викликаємо його, комп'ютер читає код і виконує в точності те, що ми написали.
Простий метод для комп'ютера може мати наступний вигляд:
void SayHello ()
{
}
Але метод не має сенсу, якщо він нічого не робить, тому давайте доповнимо код між фігурними дужками.
void SayHello ()
{
Console.WriteLine ("Hello");
}
(Щоб додати коду акуратний вигляд, необхідно створити відступи в методі за допомогою клавіші TAB)
Якщо зараз викликати цей метод, то на екран буде виведено слово «Hello». Це не надто складне завдання, тому і метод досить простий.
Що означає VOID?
Дивне слово «void» в наведеному вище прикладі може дещо спантеличити і ви можете поцікавитися навіщо взагалі ми його використали. Давайте коротко розглянемо його. Просто подумайте про свій улюблений фільм про космічні подорожі: уявіть безмежний, порожній простір у Всесвіті. Void означає «нічого».
Використання слова «void» перед ім'ям методу означає, що коли завершується його виконання, повертається пусте значення, тобто нічого не повертається. Це не означає, що метод не виконує жодних дій, а скоріше те, що по завершенні відведеної операції він ніяких значень не повертає. У наведеному вище прикладі методу «SayHello» нам це чудово підходить, оскільки після написання слова «Hello» повертати нічого не потрібно. От і все, що потрібно було зробити.
Ви зможете краще зрозуміти сенс цього слова, коли ми будемо розглядати випадки, де метод повинен буде повертати деякий результат. Ми розглянемо цей приклад трохи пізніше.
Будівельний блок: Оголошення і виклик методу
Найчастіше в класі є один або декілька методів. Вони виконують певні дії. Методами вони називаються тому, що саме в них описується метод виконання дій: покрокові інструкції, що пояснюють порядок опреацій.
class Person { // Поля public string firstName; public string lastName; // Метод public void ShowFullName() { Console.WriteLine("Name is " + this.firstName + " " + this.lastName); } … }
Person Jiminy; Jiminy = new Person(); Jiminy.firstName = "Jiminy"; Jiminy.lastName = "Cricket"; Jiminy.ShowFullName();
Параметри метода
У попередньому розділі ми коротко ознайомилися з методами, але про них можна розповісти набагато більше. У цій главі ми розглянемо більш докладні характеристики методів. У першу чергу, вам буде досить основ, але на певному етапі буде потрібно розуміння того, як відправляти значення в метод і отримувати значення з нього.
Уявімо, що вам потрібно, щоб комп'ютер вивів на екран наступний текст:
Hello Jo
Hello Sam
Hello You
Ось один спосіб, як це зробити: можна було б написати окремий метод для кожного випадку:
void WriteHelloJo ()
{
Console.WriteLine ("Hello Jo");
}
void WriteHelloSam ()
{
Console.WriteLine ("Hello Sam");
}
void WriteHelloYou ()
{
Console.WriteLine ("Hello You");
}
і потім викликати їх наступним чином:
WriteHelloJo ();
WriteHelloSam ();
WriteHelloYou ();
Але це здається зайвою витратою сил, оскільки три методи дуже схожі один на одного. А що якщо використовувати один метод WriteHello і при кожному його виклик просто повідомляти потрібну частину, яка відрізняється від попередньої.
У цьому випадку можна написати наступний метод:
void WriteHello (string someName)
{
Console.WriteLine ("Hello" + someName);
}
і потім викликати метод таким чином:
WriteHello ("Jo");
WriteHello ("Sam");
WriteHello ("You");
Як видно, цей код дозволяє скоротити як займаний простір, так і зусилля. Потрібно завжди намагатися робити код як можна більш коротким. За великим рахунком, чим коротше програма, тим розумніша програміст.
При написанні методу подібним «розумним» чином,
void WriteHello (string someName)
{
Console.WriteLine ("Hello" + someName);
}
ми фактично кажемо: «Кожного разу при виклику цього методу я буду підставляти рядок символів з певним ім'ям. Будь-який підставлений рядок повинен виводитися після слова «Hello».
Код в дужках (string someName) називається параметром. Параметр дозволяє підставляти значення в метод при його виклику.
Коли вас навчали додаванню чисел, вчитель не розповідав про кожну можливості, він просто навчив вас методу і потім поставив вам різні завдання: «Додайте 2 і 5. Тепер додайте 7 і 3 ».
Це схоже на те, як якби вчитель виклав вам метод додавання чисел і підставляв щоразу різні параметри. Неважливо, які це були б параметри, ви б змогли знайти відповідь, бо знали б метод.
Для комп'ютера не має значення, яке ім'я ви присвоїли параметру, важливо щоб воно було єдиним при використанні в усьому методі.
Наприклад, наступний код буде виконано правильно:
void WriteHello (string x)
{
Console.WriteLine ("Hello" + x);
}
А цей - ні:
void WriteHello( string someName )
{
Console.WriteLine( “Hello ” + someBodysName );
}
Можете знайти помилку? Параметри «SomeName» і «someBodysName» відрізняються - це заплутає нашого «електронного» друга і він «розгнівається».
Крім того, можна на повних правах використовувати більше одного параметру в методі. Для цього їх потрібно просто розділити комами:
void WriteHello( string firstName, string lastName )
{
Console.WriteLine( “Hello ” + firstName + “ ” + lastName );
}
Але потім при виклику методу важливо підставити правильне кількість значень
WriteHello( “Jiminy”, “Cricket” );
WriteHello ("Чорт забирай", "Боротьба");
У даному випадку на екран буде виведено текст «Hello Jiminy Cricket». («Hello чорт забирай Крикет».)
Відправлення невірних типів параметрів
Уявіть, що коли ви вперше вивчали додавання чисел, ваш учитель несподіваного задав вам таке завдання: «Складіть число 5 і квітка».
Що б ви стали робити? Напевно відповіли б, що квітка це не число і додавання неможливе. Правильно.
Подібним чином комп'ютеру не сподобається, якщо ви вкажете значення невірного типу. Така помилка зустрічається часто серед програмістів. Тому якщо щось йде не так, поверніться і переконайтеся, що вказані вами значення мають тип, відповідний визначеному в методі.
А потім, кожен раз при виклику методу ми повинні переконатися, що підставляємо правильний тип значень в ці параметри. У наведеному нижче прикладі ми підставляємо два цілих числа, оскільки параметри методу «LuckyNumber» були визначені як цілі числа.
Будівельний блок: Параметри
Щоб підставити значення в метод, необхідно визначити в ньому параметри:
class Person { // Поля string firstName; string lastName; // Метод public void LuckyNumber( int numberOfTeeth, int age ) { Console.WriteLine( “Счастливое число “ + numberOfTeeth * age ); } … }
Person jiminy; jiminy= new Person(); jiminy.LuckyNumber(24, 14);
Наведені досі методи виводили якийсь текст на екран і потім просто поверталися назад до рядка, що викликав їх, як би кажучи: «Я свою справу зробив. Повернувся у вихідну точку». Однак, іноді може виникати необхідність повернення деякого значення в рядок, з якого цей метод був викликаний.
Наведемо приклад. Ми напишемо метод, який буде виконувати пошук кількості кінцівок зазначеної тварини і потім відправляти отримане число туди, звідки він був викликаний.
Далі визначається порядок створення методу. Слід пам'ятати, що метод це частина, в якій ми вчимо комп'ютер ЯК виконувати певну дію, записуючи послідовність операцій. Спочатку я напишу те, чого хочу добитися від комп'ютера українською мовою, а потім на C #:
Якщо тварина, про яку ми говоримо - слон, то number of legs = 4.
В іншому випадку, якщо тварина, про яку ми говоримо - індик, то number of legs = 2.
В іншому випадку, якщо тварина, про яку ми говоримо - устриця, то number of legs = 1.
В іншому випадку, якщо ми говоримо про будь-яких інших тварин, то number of legs = 0.
int NumberOfLegs (string animalName)
{
if (animalName == "слон") / / Якщо назва тварини - слон
{
/ / Повертане значення 4
return 4;
}
else if (animalName == "індичка") / / В іншому випадку, якщо тварина - індичка
{
/ / Повертане значення 2
return 2;
}
else if (animalName == "устриця") / / В іншому випадку, якщо тварина - устриця
{
/ / Повертане значення 1
return 1;
}
Else / / В іншому випадку (при всіх інших умовах)
{
/ / Повертане значення 0
return 0;
}
}
і потім ми могли б викликати метод: Викличемо його двічі:
1. int i; / / Створення змінної «i» цілочисельного типу для зберігання значення числа кінцівок
2. i = NumberOfLegs ("індичка"); / / Тепер i = 2 з методу NumberOfLegs вище
3. Console.WriteLine ("У індички" + i + "кінцівок");
4. i = NumberOfLegs ("мавпа"); / / Тепер i = 0 з методу NumberOfLegs вище
5. Console.WriteLine ("У мавпи" + i + "кінцівок");
У рядку 3 на екран виводиться текст «У індички 2 кінцівок», а по рядку 5 - «У мавпи 0 кінцівок». Отже, метод повертає значення, яке можна включити безпосередньо в рядок коду, звідки був викликаний метод.
Чому ми визначили метод саме так?
int NumberOfLegs (string animalName)
{
...
}
а не ось так:
void NumberOfLegs (string animalName)
{
...
}
або таким чином:
string NumberOfLegs (string animalName)
{
...
}
А зробили так ми саме тому, що нам необхідно, щоб метод повертав ціле число в даному випадку, а не «порожнє» значення (void), не рядок літер, а саме ціле число. А для роботи з цілими числами використовується тип даних «Integer» або «int» в скороченому варіанті.
При написанні методу ми завжди вказуємо тип даних, що повертаються цим методом. Якщо немає необхідності повертати значення, ми використовуємо «void» для повернення порожнього значення.
void JustWriteSomething (string someThing)
{
Console.WriteLine (someThing);
}
І нарешті, можливо ви здогадалися, що слово «return» фактично повертає значення. Коли комп'ютер зустрічає слово «return» відбувається вихід з методу і повернення запитуваного значення.
Повертаються значення потім автоматично стають доступними в будь-якому місці, де ми викликаємо метод.
Наприклад, повернене значення ми могли б використовувати наступним способом:
Спочатку ми могли б зберегти відповідь у змінній і потім використовувати значення змінної в окремому виразі.
Або ми могли б викликати метод безпосередньо у виразі WriteLine наступним чином:
Як і поля (див. попередню главу), методи можна викликати з інших класів. Таку можливість можна дозволити або заборонити.
За замовчуванням, всі методи будуть розглядатися як private (закриті), це означає, що їх можна використовувати тільки усередині свого класу. Щоб дозволити їх використання з інших класів, можна додати слово «public» в початок оголошення.
public void JustWriteSomething (string someThing)
{
Console.WriteLine (someThing);
}
У реальному світі доступ людей без спеціального дозволу до деяких зонах заборонено. Наприклад, в ресторанах тільки кухарі та офіціанти можуть проходити на кухню, яка є закритою зоною. У той же час столова кімната відкрита для вільного доступу відвідувачів і в ній можуть знаходитися будь-які особи. Подібним чином деякий код закритий для інших класів.
В одному з розділів цієї книги ми вже розглядали приклад з закритими і відкритими полями. Давайте доповнимо наш приклад і включимо закриті (Private) і відкриті (Public) методи в клас «Animal» і потім намагаємося звернутися до них з класу «Zoo».
class Animal
{
public string kindOfAnimal;
public string name;
public int numberOfLegs;
public int height;
public int length;
public string color;
bool hasTail;
protected bool isMammal;
private bool spellingCorrect;
public string GetFoodInfo ()
/ / Відкритий метод, який отримує інформацію про те, чим харчується тварина
{
/ / Уявімо, що тут розташований код, який виконує пошук по базі даних
...
}
private void SpellingCorrect ()
/ / Закритий метод для перевірки правильності написання виду тварини
{
/ / Уявімо, що тут розташований код для перевірки правопису
...
}
protected bool IsValidAnimalType ()
/ / Захищений метод, який приймає рішення про існування зазначеного виду тварини
{
/ / Уявімо, що тут розташований код для перевірки існуючих видів тварин
...
}
...
}
class Zoo
{
Animal a = new Animal ();
a.name = "Kangaroo";
string food;
bool animalExists;
/ / Наступний код буде виконано успішно, оскільки класу «Zoo» дозволено
/ / Звертатися до відкритих методів у класі «Animal»
food = a.GetFoodInfo (); / / Виклик відкритого методу
/ / Обидві наступні рядки НЕ будуть виконані, оскільки класу «Zoo»
/ / Не дозволено звертатися до закритих або захищених методів
a.spellingCorrect (); / / спроба виклику закритого методу
animalExists = a.IsValidAnimalType (); / / спроба виклику захищеного методу
}
Дуже часто вам будуть зустрічатися класи з досить специфічним типом методу який називають «конструктором». Ім'я методу-конструктора відповідає імені класу і тип повернення в нього не включається.
Даний метод називається конструктором, оскільки він допомагає «конструювати» або будувати об'єкт при першому його створенні. Створення цього методу в класах вважається хорошою практикою.
class Person
{
/ / Поля
string firstName;
string lastName;
/ / Метод-конструктор для класу Person
public Person ()
{
firstName = "Johnny";
lastName = "Rocket";
}
}
Метод-конструктор обробляється по-особливому: він виконується автоматично при кожному створенні екземпляра класу.
Нагадування:
Під «екземпляром класу» ми розуміємо певний об'єкт класу. Наприклад, в одному з попередніх розділів по об'єктах ми виділили «Горила Джеремі» як певний об'єкт або екземпляр класу «Animal».
Отже, якщо ми виконаємо наступний код ...
Person p = new Person ();
Console.WriteLine (p.lastName);
то результатом буде слово «Rocket» на екрані. Створивши об'єкт «Person» ми автоматично і непомітно виконали метод конструктора «Person», який в цьому випадку задає значення «Rocket» для lastName.
Наведемо аналогічний приклад з реального життя. У деяких країнах при народженні дитини його реєструють згідно закону перш ніж він покине лікарню, щоб він міг відразу прийняти участь у житті суспільства.
Цю дію можна порівняти з методом-конструктором, що виконується для класу. Перш ніж новий екземпляр класу зможе щось зробити, виконується метод-конструктор. У нього можна включити будь-які дії, які повинні виконуватися автоматично, перш ніж об'єкт буде вважатися «готовим до життя».
Конструктори з параметрами
У метод-конструктор можна включити параметри. Наведемо приклад класу з двома різними методами-конструкторами:
class Person
{
/ / Поля
string firstName;
string lastName;
/ / Перший метод-конструктор
public Person ()
{
firstName = "Johnny";
lastName = "Rocket";
}
/ / Другий метод-конструктор
public Person (string f, string l)
{
this.firstName = f;
this.lastName = l;
}
}
І тепер у нас є два різні способи конструювання об'єкту:
Наприклад, цей:
Person p = new Person ();
І в поле p.lastName буде автоматично підставлено значення «Rocket».
Або ж цей:
Person p = new Person ("Jiminy", "Cricket");
І в поле p.lastName буде підставлено значення «Cricket».
Пам'ятайте, що слово «this» відноситься до «того об'єкту, який ми створюємо». Тобто, фактично говориться «підставляти в поля імені і прізвища цього нового об'єкта будь-які значення, передані методу-конструктору».
У реальному світі події відбуваються безперервно. Деякі події не залежать від нас. Наприклад, схід та захід сонця (хотів би я подивитися, як ви намагаєтеся примусити сонце вставати і сідати). Інші події можуть викликатися нами, скажімо, ми можемо змусити гучномовець видавати звуки.
комп'ютерному світі в основному зустрічаються такі події:
Натискання кнопки на екрані монітора
Закінчення часу таймера
Переміщення миші
Натискання клавіші на клавіатурі
Очевидно, що натисканням кнопки ми хочемо змусити комп'ютер виконати певну дію, якщо ні, то навіщо взагалі вона нам потрібна. Але комп'ютер чекає, що ви скажете йому, що натискання цієї кнопки має значення для вас, а також вкажіть дію, яку потрібно виконати при цьому.
Давайте розглянемо приклад з натисканням кнопки, оскільки це, можливо, найбільш поширене подія, і детально розберемо порядок роботи. Припустимо, у вашій програмі є об'єкт кнопки з ім'ям mrButton і словами «Click me» на неї. Навіть знаєте що, спробуйте робити все самі по ходу обговорення. Для початку:
Щоб запустити Visual C # Express в меню «Пуск» вкажіть «Усі програми» і потім «Microsoft Visual C # 2005 Express Edition».
Створіть новий проект програми Windows: У меню File («Файл») виберіть Create project («Створити проект») і виберіть тип проекту Windows Application («Додаток Windows»).
У Visual C # Express відкриється декілька файлів з «кодом-скелетом» програми.
У вікні браузера рішень справа (де перераховані всі файли) видаліть файл з ім'ям Form1.cs.
Двічі клацніть ім'я файлу Program.cs і видаліть весь автоматично вставлений «скелет» коду.
Щоб створити програму з примірником кнопки наберіть наступний код у вікні Program.cs в точності так, як показано нижче (написання слів курсивом або жирним шрифтом можна опустити)
using System;
using System.Windows.Forms;
class MyButtonClass: Form
{
private Button mrButton;
/ / Метод-конструктор
public MyButtonClass ()
{
mrButton = new Button ();
mrButton.Text = "Click me";
this.Controls.Add (mrButton);
}
/ / Основний метод
static void Main ()
{
Application.Run (new MyButtonClass ());
}
}
Виконайте програму за допомогою клавіші F5 на клавіатурі (або клацніть зелену кнопку «Виконати»). Якщо виникнуть повідомлення про помилки, ретельно перевірте код на предмет помилок. Якщо програма буде виконана успішно, то ви повинні побачити форму з кнопкою «Click me». Поки при натисканні на кнопку ніяких дій відбуватися не буде. Зовсім не те, що ви чекали, я знаю, але ми прийдемо і до цього.
Подія натискання кнопки
Вказівка дії у разі події
Тепер, коли нам відомо, що потрібно зробити при натисненні на кнопку, ми повинні вказати метод, за яким буде виконуватися дія. Типи методів, які повідомляють комп'ютера про дії у разі подій називаються методами обробника подій, оскільки вони «обробляють» подію. У наведеному нижче прикладі виділений жирним код просто змінює напис на кнопці, тому він зовсім короткий.
using System;
using System.Windows.Forms;
class MyButtonClass: Form
{
private Button mrButton;
/ / Метод-конструктор
public MyButtonClass ()
{
mrButton = new Button ();
mrButton.Text = "Click me";
this.Controls.Add (mrButton);
}
/ / Основний метод
static void Main ()
{
Application.Run (new MyButtonClass ());
}
/ / Метод обробника подій
void MyButtonClickEventHandler (object sender, EventArgs e)
{
mrButton.Text = "You clicked me!";
}
}
Програма, як і раніше виконується?
Зупиніть її (натисніть кнопку X у верхньому правому куті вікна, в якому відкрита форма)
Додайте виділений жирним код у вашу програму і натисніть клавішу F5 для виконання зміненої програми.
Спробуйте тепер натиснути кнопку «Click me» Бррр! І тепер нічого?
Якщо ви прочитали главу про методи, то дізнаєтеся основну структуру наведеного вище методу. Слово «void» означає, що по завершенні методу нічого не повертається. Словом «MyButtonClickEventHandler» ми назвали цей метод.
Тоді все стає трохи дивним. Можливо ви зрозумієте, що в дужках присутній два параметри, але вони не підходять: (object sender, EventArgs e). Мені не хотілося б повідомляти вам такі неприємні новини, але з методами обробників подій не можна використовувати власні типи параметрів. При виклику такого методу система сама автоматично підставляє певні параметри і нічого з цим вдіяти ми не зможемо.
Тому доведеться просто змиритися і завжди використовувати очікувані типи параметрів з обробником подій. У випадку з подією натискання на кнопку і багатьма іншими, підставляються параметри мають тип «object» і «EventArgs». У наведеному вище прикладі ми вибрали імена параметрів «sender» і «e», але ми могли б вибрати будь-які імена - для комп'ютера важливі імена типів цих параметрів. Наприклад, наступний код буде працювати в точності так само, як і код в прикладі вище. Якщо хочете, можете самі перевірити це, змінивши імена параметрів у вашій програмі на «x» і «y».
void MyButtonClickEventHandler (object x, EventArgs y)
{
mrButton.Text = "You clicked me!";
}
У першому параметрі зазвичай міститься деяка інформація про об'єкт, що ініціював подію. Другий параметр відноситься до даних про саму подію.
Також слід знати наступне - незважаючи на те, що системою завжди підставляються деякі значення в ці два параметри, часто не буде необхідності в їх використанні - вони відправляються в метод обробника подій «на всякий випадок».
Підключення методу обробника подій до події
Ви дивуєтеся чому нічого не відбувається при натисканні на кнопку? Справа в тому, що вказаний метод викликається тільки тоді, коли ми зв'яжемо з ним подію натискання на кнопку. У програмі потрібно вказати, що при натисканні на кнопку необхідно перейти до певного обробника подій.
Це абсолютно очевидно, коли в програмі використовуються різні кнопки і кілька обробників подій. Звідки комп'ютера буде відомо, який метод виконувати при натисканні на кожну кнопку?
Код для зв'язування події об'єкта з методом обробника події виглядає теж трохи дивно. І ми знову виділимо його жирним.
using System;
using System.Windows.Forms;
class MyButtonClass: Form
{
private Button mrButton;
/ / Метод-конструктор
public MyButtonClass ()
{
mrButton = new Button ();
mrButton.Text = "Click me";
mrButton.Click + = new System.EventHandler (MyButtonClickEventHandler);
this.Controls.Add (mrButton);
}
/ / Основний метод
static void Main ()
{
Application.Run (new MyButtonClass ());
}
/ / Метод обробника подій
void MyButtonClickEventHandler (object sender, EventArgs e)
{
mrButton.Text = "You clicked me!";
}
}
З комп'ютерної на нашу мову це можна перекласти наступним чином:
До події натискання на кнопку додати новий метод обробника подій, який називається MyButtonClickEventHandler.
Отже, при натисненні на кнопку, наведена вище рядок коду направляє програму до методу обробника подій. При його виконанні напис на кнопці змінюється на «You clicked me!»
Щоб спробувати цей код, зупиніть свою програму, додайте в неї виділений жирним код (у відповідне місце) і натисніть клавішу F5 для виконання програми. Натисніть на кнопку і її напис зміниться. Робочу програму - приклад події натискання на кнопку можна знайти в папці прикладів до цієї книги (Програма 5).
У цьому розділі ми опишемо основну структуру методу обробника подій миші. Ймовірно, в цьому випадку ви захочете використовувати інформацію, що підставляється в параметр MouseEventArgs, щоб з'ясувати, наприклад, яка з кнопок миші натискається.
public void TheMouseIsDown (object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
this.Text = "Натиснута ліва кнопка миші";
}
}
А далі показано як подію можна пов'язати з методом. У цьому прикладі йдеться: «Якщо при виконанні цієї програми натискається кнопка миші, перейти до методу TheMouseIsDown», якому відомо як обробляти події миші:
this.MouseDown + = new MouseEventHandler (TheMouseIsDown);
Можна зробити навіть ще трохи краще. Коли ініціюється наступний обробник, код, написаний в ньому, робить вікно ширше або вже залежно від натискаємо кнопки.
public void TheMouseWasClicked(object sender, MouseEventArgs e)
{
/ / При натисненні лівої кнопки
if (e.Button == MouseButtons.Left)
{
/ / Розширення поточного вікна
this.Width = this.Width + 100;
}
else if (e.Button == MouseButtons.Right)
{
/ / Звуження поточного вікна
this.Width = this.Width - 100;
}
}
Наступний обробник подій дозволяє виявити переміщення миші і малювати коло в тому місці, де знаходиться курсор:
public void TheMouseMoved (object sender, MouseEventArgs e)
{
/ / Підготовка області малювання
System.Drawing.Graphics g = this.CreateGraphics ();
/ / Використання червоної ручки
System.Drawing.Pen redPen = new System.Drawing.Pen (Color.Red, 3);
/ / Малюємо коло (еліпс, точки якого рівновіддалені від центру)
/ / Лівий верхній кут квадрата має координати X і Y поточного положення миші
g.DrawEllipse (redPen, e.X, e.Y, 40, 40);
/ / Очищення
g.Dispose ();
}
На наступному знімку екрана показано як це виглядає при переміщенні миші:
Простори імен та Поштова служба
У світі існують сотні, якщо не тисячі вулиць імені Леніна. Яким чином лист, відправлений на адресу по вулиці Леніна знаходить свого одержувача? Природно, адреса складається не тільки з вулиці. Ми, як правило, щонайменше, додаємо назву міста і назва країни.
Очевидно, якщо ми напишемо:
Вулиця ім. Леніна, 17
Вулиця ім. Леніна, 82
то не буде різниці між цими вулицями і листоноша буде жахливо розчарований.
Замість цього можна було б написати так:
Вулиця ім. Леніна, 17. м. Москва
Вулиця ім. Леніна, 82. м. Алмати.
Так-то краще, але що якщо буде два міста з назвою Москва! Тоді краще всього додати ще й назву країни.
Вулиця ім. Леніна, 17. м. Москва. Російська Федерація.
Вулиця ім. Леніна, 82. м. Алмати. Республіка Казахстан.
Адреса з таким же успіхом можна написати і навпаки:
Російська Федерація. м. Москва. Вулиця ім. Леніна, 17.
Республіка Казахстан. м. Алмати. Вулиця ім. Леніна, 82
Тепер лист повинен дійти до адресата без проблем. Наприклад, у другому прикладі, лист доставлять до Республіки Казахстан. Потім з аеропорту його відправлять у місто Алмати. А потім листоноша піде на вулицю ім. Леніна і знайде будинок під номером 82.
Формат [Республіка Казахстан.Алмати.вул. ім. Леніна] можна вважати «простором імен» для повідомлень.
Простори імен та програмний код
Так яке відношення все це має до програмування?
Припустимо, що розробниками корпорації Microsoft написаний клас «Point», який використовується для малювання фігури в певній точці, але ви також створили клас під назвою «Point», наприклад для завантаження фотографії людини, що вказує на що-небудь.
Очевидно, що ці два класи виконують абсолютно різні дії, але обидва їх можна назвати «Point». Звідки програма буде знати з яким класом працювати?
Безумовно, має сенс якось використовувати різні імена. У середовищі. NET для цього можна використовувати різні простори імен. Наприклад, так:
Microsoft.Drawing.Point
Susy.PictureStuff.Point
Імена класів збережені («Point»), але «простір імен» перед ім'ям класу дозволяє чітко бачити, де який клас. І тепер, якщо мені потрібно використовувати клас Point для Susy, я міг би створити об'єкт Point за допомогою наступного методу-конструктора:
Susy.PictureStuff.Point SusyPoint = new Susy.PictureStuff.Point ();
А для роботи з класом Point від Microsoft я б використав наступний код:
Microsoft.Drawing.Point MicrosoftPoint = new Microsoft.Drawing.Point ();
Незважаючи на те, що обидва мої об'єкти мають один тип класу «Point», вони виконують різні дії.
Присвоєння простору імен власному класу
Розміщення власного класу в простір імен вкрай просто. Замість того, щоб писати клас наступним чином:
class Animal
{
...
}
включіть його в наступний код:
namespace Susy
{
class Animal
{
...
}
}
або зробіть так, якщо хочете:
namespace Susy.FunStuff
{
class Animal
{
...
}
}
Можна створити будь-який простір імен, який, як вам здається, має сенс. Просто розділяйте свої слова крапкою (.).
В останньому наведеному прикладі, клас Animal тепер входить у простір імен Susy.FunStuff.
Ви також побачите, що всі бібліотеки коду від Microsoft, а також інших організацій, поміщаються в простори імен. Тому щоб використовувати код з таких бібліотек, необхідно розуміти, як працювати з просторами імен.
Примірник або об'єкт наведеного вище класу можна розглядати за допомогою методу-конструктора класу наступним чином:
Або, якщо б нам потрібно було використовувати багато об'єктів з одного простору імен, і при цьому не хотілося б кожного разу писати «Charles.SchoolUtilities», то ми могли б вжити ключове слово «using» на початку програми, щоб повідомити комп'ютера, що в надалі будемо застосовувати цей простір імен. Наприклад:
/ / Говоримо комп'ютера, що будемо використовувати класи з цього простору імен
using Charles.SchoolUtilities;
/ / Створення об'єкта Animal з простору імен Charles.SchoolUtilities
Animal cat = new Animal ();
Будівельний блок: Простору імен
Для логічного об'єднання подібних класів і їх розрізнення рекомендується завжди поміщати клас на значемий простір імен.
namespace Charles.SchoolUtilities { class Animal { } }
Charles.SchoolUtilities.Animalcat = new Charles.SchoolUtilities.Animal();
Оскільки метою книги є тільки знайомство з програмуванням, ми не станемо розглядати занадто складні речі, тому не розповімо багато чого про спадкування.
Однак, оскільки іноді вам буде зустрічатися оголошення класів наступного вигляду
class MyFancyClass: Form
{
...
}
замість цього
class MyFancyClass
{
...
}
ми повинні дати пояснення з частини коду, що починається з двокрапки (:).
Спадкування серед людей
Людина, як правило, успадковує певні якості від своїх батьків. У вас може бути колір волосся мами, а ніс - тата.
Хоча це не означає, що ви повністю схожі на свою матір чи батька, але певні якості «закладені» в вас при народженні. Ви також будете володіти різними унікальними якостями і здібностями крім тих, які отримали від батьків.
Спадкування коду
При написанні програмного коду було б також корисним мати можливість наслідування всього набору здібностей існуючого класу, будь то власний клас або чийсь ще.
Наведемо приклад. Ми визначили два класи - «Animal» і «Bird», і клас «Bird» успадковує ознаки класу «Animal».
class Animal
{
public string kindOfAnimal;
public string name;
public int numberOfLegs;
public int height;
public int length;
public string color;
bool hasTail;
protected bool isMammal;
private bool spellingCorrect;
...
}
class Bird: Animal / / Клас «Bird» успадковує від класу «Animal»
{
public string featherColor;
...
}
У реальному світі птах - це вид тварини, але деякі ознаки птахів не відповідають ознакам всіх тварин. Тоді має сенс класу Bird переймати всі ознаки класу Animal і мати ряд додаткових ознак. У цьому випадку ми визначили одне спеціальне поле тільки для птахів - featherColor.
Отже, коли ми пишемо
class Bird: Animal
{
...
}
ми фактично кажемо: «Я визначаю новий клас" Bird ", але він повинен автоматично успадковувати всі властивості класу «Animal». Часто кажуть, що клас «Bird» є похідним від класу «Animal».
При створенні екземпляра «Bird» ми можемо тут же звертатися до полів як класу «Animal», так і «Bird» (якщо вони не є закритими):
Bird b = new Bird ();
b.kindOfAnimal = "Tawny Eagle";
b.isMammal = false;
b.featherColor = "Tawny";
Щоб було зрозуміло, ми виключили методи в класах «Animal» і «Bird» у прикладі вище, але для них діє те ж правило. Похідний клас може викликати будь-які методи в батьківському класі, якщо вони не оголошені закритими.
Інший приклад - Спадкування деяких можливостей роботи з вікнами в вашій програмі.
Припустимо, вам потрібно написати програму, що виконується в звичайному вікні. Вам необхідні можливості зміни розміру, розгортання, звертаючи, перетягування вікна і деякі інші. Має сенс, щоб ваш клас «успадковував» можливості класу, який вже працює з подібним типом інтерфейсу. Звичайним вибором стає клас System.Windows.Forms.Form.
Отже, коли ми пишемо
class MyFancyClass: Form
{
...
}
ми фактично кажемо: «Я пишу власний клас, але він повинен автоматично успадковувати всі можливості класу« Form ».
Розглянуті в цьому розділі питання розбираються на практиці у Розділі III по System.Windows.Forms.
Коли слід використовувати спадкування
Для використання класу зовсім не обов'язково успадковувати від нього поля! Спадкування найкраще працює в тих випадках, коли те, чого ви намагаєтеся домогтися, можна отримати від існуючого класу, і хочеться розширити або налаштувати його.
Будівельний блок: Спадкування
Клас можна змусити успадковувати ознаки і здатності іншого класу.
У наступному прикладі клас «Guitarist» успадковує три поля з класу «Musician» і має два власні поля.
Двокрапка (:) говорить комп'ютера, що потрібно змусити новий клас (Guitarist) успадковувати поля класу, написаного праворуч від двокрапки.
public class Musician { public string name; public int age; public bool canSing; } public class Guitarist : Musician { public string guitarType; public string guitarBrand; } Guitarist g = new Guitarist(); g.name = "Jimbo van Helsdingen"; g.ageInYears = 28; g.canSing = false; g.guitarType = ”Acoustic”; g.guitarBrand = ”Gibson”;