Програмування на мові ruby, частина 3

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

З прикладу видно, що для строкового об'єкта викликається метод з ім'ям length '.

З цього прикладу видно, що рішення про те який метод викликати приймається під час виконання і, що вибір цей залежить від вмісту змінної. (В першому випадку змінна foo представляється як строкова змінна, в другому - як масив прим. Перекл.).

У читача може виникнути питання: "Як же так? Адже довжина рядка і довжина масиву вважаються по різному?". Не варто турбуватися. На щастя, Ruby автоматично вибирає відповідний ситуації метод. Ця особливість в об'єктно-орієнтованому програмуванні називається поліморфізмом.

Немає ніякої необхідності знати про те як працює той чи інший метод, але кожен повинен знати про те які методи є у об'єкта. При виклику невідомого об'єкту методу, виникає помилка. Наприклад, спробуйте викликати метод "length" для об'єкта "foo", присвоївши йому попередньо значення "5".

Я вже згадував про спеціальну псевдопеременной self. Вона визначає об'єкт, чий метод був викликаний. Однак вказівка ​​цієї змінної дуже часто опускається, наприклад:

може бути скорочено до

Ці два виклики ідентичні один одному, просто другий спосіб є скороченим варіантом першого.

Реальний світ складається з об'єктів, які можуть бути класифіковані. Наприклад, однорічний малюк, побачивши собаку, думає про неї як "гав-гав". У термінах об'єктно-орієнтованого програмування, "гав-гав" - це клас. а об'єкт, що належить класу - екземпляр класу.

В Ruby, як і в інших об'єктно-орієнтованих мовах програмування, спершу визначається клас, щоб описати поведінку об'єкта, а потім створюється екземпляр класу - окремий об'єкт. А тепер давайте визначимо клас.

Опис класу має починатися з ключового слова class і закінчуватися ключовим словом end. Ключове слово def в даному контексті починає визначення методу класу.

Отже, ми описали клас з ім'ям Dog ', а тепер створимо об'єкт.

Цей код створює новий екземпляр класу Dog і пов'язує його зі змінною tommy. Метод new 'будь-якого класу створює новий екземпляр цього класу. Тепер змінна tommy має властивості класу Dog і може "прогавкать" (метод bark ').

спадкування

Ви коли небудь задавалися питанням - як різні люди класифікують об'єкти? Наприклад, як люди бачать собаку? Математик може описати собаку як комбінацію чисел і геометричних фігур. Фізик - як результат роботи природних і штучних сил. Моя сестра (біолог) може уявити собаку як різновид загону псових домашніх (canine domesticus). Для неї собака - це різновид псових, псові - різновид ссавців, а ссавці - завжди тварини.

Звідси видно, що класифікація об'єктів має форму ієрархії, хоча і не завжди. Подивимося, як це можна реалізувати в Ruby.

Відомо, що властивості батьківського класу не завжди успадковуються нащадками. Наприклад, пінгвіни не можуть літати, хоча і є птахами. Однак пінгвіни несуть в собі багато інших риси, властиві птахам, наприклад, вони відкладають яйця. Подібні випадки можуть бути реалізовані і в Ruby, однак залишаю читачам можливість розібратися з цим самим.

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

перевизначення методів

Ми вже спостерігали відмінності в поведінці примірників дочірніх класів після перевизначення методів батьківського класу. Подивіться на приклад нижче:

У дочірньому класі, переобумовленої метод батьківського класу, можна викликати оригінальний метод батька за допомогою ключового слова super '. Спробуйте запустити цей код:

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

Ще про методи

Можливість виклику методу може бути обмежена. Для функції (яка визначається на верхньому рівні) дивіться нижче:

Якщо визначення функції знаходиться за межами опису класу, то вона додається як метод класу Object. Клас Object є базовим для всіх інших класів - в Ruby все класи є нащадками класу Object. Таким чином, метод sqr 'може викликатися з інших класів.

Тепер, коли будь-який клас може викликати метод sqr ', давайте спробуємо викликати його за допомогою псевдопеременной self':

Як показано вище, виклик функції за допомогою self 'призводить до видачі повідомлення про помилку. Це повідомлення недостатньо зрозуміло (інтуїтивно), що воно означає?

Суть в тому, що функції, визначені за межами будь-якого класу повинні викликатися як прості функції, а не як методи. Подивіться яке повідомлення про помилку виходить при виклику не визначеного методу.

Методи, визначені як прості функції, повинні викликатися як прості функції, подібно до функцій C ++, навіть в межах класу.

Область видимості методу може бути обмежена ключовими словами "public" і "private", де public - визначає загальнодоступні методи класу, а private - приховані, які можуть бути викликані тільки з інших методів класу.

З цього прикладу все повинно бути зрозуміло.

Поодинокі (Singleton) методи

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

Де t1 і t2 - належать одному і тому ж класу і тим не менше, для примірника t2 переопределяется метод size ', забезпечуючи його індивідуальність. Такий специфічний метод називається одиничний метод (singleton method).

Як приклад застосування одиничного методу можна привести кнопки у вікні програми з графічним інтерфейсом, де кожна кнопка повинна виконувати свої дії після натиснення. Ми можемо перевизначити метод, що обробляє натискання у кожної з наявних кнопок.

Модулі в Ruby дуже схожі на класи, але використовуються для групування споріднених класів в одному місці. Ось три основні відмінності модулів від класів:

  1. Модулі не мають примірників модулів.
  2. Модулі не можуть мати дочірні модулі.
  3. Модулі визначаються конструкцією module. end.

Грубо кажучи, існують дві основні причини використання модулів. Перша - зібрати методи і константи в одному місці. наприклад:

Оператор. 'Вказує на те, що константа визначена у відповідному модулі або класі. Щоб звертатися до методів або констант безпосередньо, слід використовувати директиву include '

Інша причина - "змішання" (mixin ') модулів. Сенс цього терміна досить складний для розуміння, тому зупинимося на ньому докладніше.

Деякі об'єктно-орієнтовані мови допускають спадкування від декількох батьківських класів, така можливість називається множинним спадкуванням. Ruby навмисно позбавлений цієї можливості. Замість цього він допускає змішання (mixin) з модулем.

Як сказано вище, модуль багато в чому схожий на клас. Методи або константи в модулі не можуть успадковуватися, але можуть бути додані в інші модулі або класи за допомогою директиви include. Таким чином, підключення модуля до визначення, додає (підмішує) властивості модуля до властивостей класу або модуля.

Змішання модулів можна спостерігати в стандартній бібліотеці, де в результаті "змішування" модулів з класом, що має метод each ', який повертає кожен елемент, останній отримує в своє розпорядження методи sort', find 'і т.п ..

Між множинним спадкуванням і "змішанням" існують такі відмінності:

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

Ці відмінності забороняють складні взаємини між класами, простота є наріжним каменем. З цієї причини Ruby не підтримує множинного спадкоємства. У мовах, що підтримують множинне спадкування, цілком може виникнути ситуація, коли класи мають кілька предків, а взаємини між екземплярами класів створюють заплутану мережу. Ситуація дуже складна для сприйняття людським мозком, принаймні - моїм.

З іншого боку, змішання представляє все це, просто як "колекцію специфічних властивостей з усього, що було додано".

Навіть в мовах з множинним спадкуванням, вважається, що краще розширювати класи з використанням змішування, ніж розробляти складні відносини спадкування. В Ruby ця ідея була просунута далі, замінивши собою ідею множинного спадкоємства.

процедурні об'єкти

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

Процедурні об'єкти створюються за допомогою вбудованого методу proc. Виконуваний код записується всередині фігурних дужок. Виклик на виконання провадиться методом call процедурного об'єкта. Дивіться нижче:

C-програмісти виявлять схожість між процедурними об'єктами і покажчиками на функції.

висновок

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

Hiran Ramankutty

Я - студент останнього курсу Урядового Коледжу Комп'ютерних Наук в місті Трикур (Trichur), Індія. Крім Linux, я з великим задоволенням займаюся вивченням фізики.