пятница, 22 июля 2011 г.

Написание собственных методов Ruby

Давайте посмотрим на написание собственных методов в Ruby с помощью простой программы r08mymethods.rb. Заметьте, что мы используем def и end для того, чтобы объявить метод. Параметры - просто список имен локальных переменных в скобках.


Мы не заявляем возвращаемого типа, метод возвращает значение выполненного выражения(оператора - statement) в методе. Рекомендуется оставить одну пустую строку между каждыми определениями метода. Скобки вокруг аргументов метода являются необязательными; по принятому соглашению, мы используем их, когда метод имеет аргументы и опускаем их, когда это не так. В Рельсах вы увидите методы, вызванные без скобок.

  1. # r08mymethods.rb  
  2. # Метод возвращает значение последней строки  
  3. # Методы, которые ведут себя как вопросы часто вызываются с прикрепленным ?    
  4. # "Опасные", предостерегающие методы или методы для изменения получателя 
  5. #(ресивера) должны вызываться с прикрепленным ! (Bang методы)    
  6. # Простой метод  
  7. def hello  
  8.   'Hello'  
  9. end  
  10. #use the method  
  11. puts hello  
  12.   
  13. # Method with an argument - 1  
  14. def hello1(name)  
  15.   'Hello ' + name  
  16. end  
  17. puts(hello1('helen'))  
  18.   
  19. # Method with an argument - 2  
  20. def hello2 name2  
  21.   'Hello ' + name2  
  22. end  
  23. puts(hello2 'Vova')  


Вывод, когда я запустила программу на своем компьютере был такой:

  1. >ruby r08mymethods.rb  
  2. Hello  
  3. Hello helen  
  4. Hello vova 


Ruby позволяет вам задать значения по умолчанию для аргументов-значений метода, которые будут использоваться, если вызывающий не передаст их в явном виде. Это делается с помощью оператора присваивания. См. пример r09mymethods1.rbsdf

  1. # r09mymethods1.rb  
  2. # интерполяция (изменение, переделка) относится к процессу вставки результата 
  3. # выражения в строковую константу  
  4. # интерполяционный оператор #{...} gets calculated separately рассчитывается отдельно 
  5. def mtd(arg1="Dibya", arg2="Shashank", arg3="Shashank")  
  6.   "#{arg1}, #{arg2}, #{arg3}."  
  7. end  
  8. puts mtd  
  9. puts mtd("ruby"


Вывод, когда я запустила программу был такой:

  1. >ruby r09mymethods1.rb  
  2. Dibya, Shashank, Shashank.  
  3. ruby, Shashank, Shashank.  


Обратите внимание, что на данный момент не существует способа, чтобы указать значение для второго параметра и использовать значение по умолчанию первого параметра.
В программе выше оператор интерполяции #{...} получал считался отдельно и результаты вычислений автоматически вставляются в строку. Когда вы запускаете эти строки, вы не видите оператора  #{...} на экране; вместо этого вы видите результаты вычислений или оценки того, что было внутри этого оператора.
Заметка: Интерполяция отсылает к процессу вставки результата выражения в строковую константу. Способ интерполировать внутри строки - это поместить выражение в символы #{and}. Пример это демонстрирует:


puts "100 * 5 = #{100 * 5}"  

Выведется:

100 * 5 = 500 

Часть #{100*5} интерполирует результат 100*5 (500) в строку на позиции, результаты которого показаны в выводе.
Пример r10aliasmtd.rb демонстрирует (вымышленное имя? ступенчатость? Aliasing) метода.

alias new_name old_name  

создает новое имя, которое отсылает к существующему методу. Когда метод является псевдонимом(?), новое имя ссылается на копию тела оригинального метода. Если метод впоследствии переопределен, псевдонимное имя будет по-прежнему вызывать оригинальное выполнение.


  1. # r10aliasmtd.rb  
  2. # alias new_name old_name  
  3. # Когда новый метод псевдоним, новое имя ссылается 
  4. # на копию тела оригинального метода  
  5.   
  6. def oldmtd  
  7.   "old method"  
  8. end  
  9. alias newmtd oldmtd  
  10. def oldmtd  
  11.   "old improved method"  
  12. end  
  13. puts oldmtd  
  14. puts newmtd  


Вывод в программе будет таким:



  1. ruby p010aliasmtd.rb  
  2. old improved method  
  3. old method  


псевдоним создает новое имя, которое ссылается на существующий метод, оператор, глобальную переменную или обратную ссылку регулярного выражения ($&, $՝, $' and $+). Локальные переменные, переменные экземпляра, переменные класса и константы не могут быть псевдонимами. Параметрами псевдонима могут быть имена или символы.

Позволяет ли нам Ruby писать функции, которые могут принять число параметров переменной? Да, смотрите следующий пример - r11vararg.rb



  1. # r11vararg.rb  
  2. # число параметров примеров переменной(?)  
  3. # Звездочка * в действительности берет все аргументы, которые посылаются в метод  
  4. # и присваивают их к массиву, названному my_string, как показано ниже  
  5. # The do end is a Ruby блок, о котором мы поговорим позже  
  6. def foo(*my_string)  
  7.   my_string.inspect  
  8. end  
  9. puts foo('hello','world')  
  10. puts foo()  


Звездочка в действительности берет все аргументы, которые вы посылаете в метод и присваивает их массиву под названием my_string. Как вы видите, используя звездочку, мы можем передавать даже в нулевых аргументах(?). В коде ниже будет представлен результат в Массиве ['hello', 'world'], написанном в первом вызове метода и пустой Массив, написанные во втором вызове метода, как вы можете увидеть в следующем выводе:


  1. >ruby p011vararg.rb  
  2. ["hello""world"]  
  3. [] 


Если Вы хотите включить опциональные аргументы (*x), они должны идти после любого неопционального аргумента:

def opt_args(a,b,*x) # right
def opt_args(a,*x,b) # wrong

Какое максимальное число параметров мы можем передавать в Ruby? Нет никакого ограничения числа параметров.

Какая очередность, в которой параметры находятся в стеке? Слева направо, как в С или справа налево, как в Паскале? Ответ - справа налево, как вы можете убедиться в этом примере r12mtdstack.rb


  1. # r12mtdstack.rb  
  2. # Последовательность, в которой параметры располагаются в стеке - слева направо  
  3. def mtd(a=99, b=a+1)  
  4.   [a,b]  
  5. end  
  6. puts mtd 


Параметры располагаются по значению или ссылке? Посмотрите в следующем примере:



  1. def downer(string)  
  2.   string.downcase  
  3. end  
  4. a = "HELLO"  
  5. downer(a)      # -> "hello"  
  6. puts a         # -> "HELLO"  
  7.   
  8. def downer(string)  
  9.   string.downcase!  
  10. end  
  11. a = "HELLO"  
  12. downer(a)      # -> "hello"  
  13. puts a         # -> "hello"  


Гэри Райт на форуме Ruby написал в ответ на некоторые посты: "Мне неловко даже думать о методах, возвращающих объекты, если вы используете это в очень специфических сокращениях для того, чтобы говорить, что методы возвращают "ссылки" объектам. Что объединяющая идея, которая помогает мне понять, как Ruby манипулирует данными - это все ссылки, а не сами объекты. Сами объекты почти полностью скрыты от программиста (за исключением С расширения) в Ruby. Все является ссылкой на объект."

Bang (!) Methods


Методы Ruby, которые изменяют объект на месте и заканчиваются восклицательным знаком, называются Bang-методами. По соглашению, знак восклицания говорит об опасности - в особенности, как опасно эквивалент с тем же именем, но без восклицательного знака.

Вы найдете много пар методов, некоторые с восклицательными знаками, и некоторые - без. Те, что без восклицательного знака выполняют действие и возвращают свежий(?) объект, отражающий результаты действия (используя строку, сортируя массив и т.д.). Bangовые варианты тех же методов выполняют действия, но они это делают на месте: вместо создания нового объекта, они изменяют оригинальный объект.

Примеры таких пар методов включают sort/sort! для массивов, upcase/upcase! для строк, chomp/chomp! для строк и reverse/reverse! для строк и массивов. В каждом случае, если вы вызываете не bangовую версию метода объекта, вы получаете новый объект. Если вы вызываете bangовую версию, вы оперируете на месте с тем же объектом, которому вы послали сообщение.

В Ruby вы можете определить имя метода, который заканчивается с восклицательной точкой или знаком. Bangовые методы вызываются и исполняются точно так же, как любые другие методы. Тем не менее, по соглашению, метод с восклицательной точкой или знаком считается опасным.


Обычно для встроенных классов, опасные обычно (хотя и не всегда) означает, что метод, в отличие от невосклицательного эквивалента, постоянно изменяет свой получатель(приемник), короче, хрень какая-то, а не перевод.


Вы увидите множество методов, некоторые с восклицательным знаком, некоторые - без. Те, что без восклицания выполняют действие и возвращают новый объект. Bangовые версии тех же методов выполняют действие, но они это делают на месте: вместо создания нового объекта, они изменяют оригинальный объект.

Несколько неbangовых методов выполняют изменения в оригинальной строке. Имена этих методов делают понятным, что это происходит (такие, как replace), даже если нет восклицательного знака в имени.

Имена методов, заканчивающихся ?
Знак вопроса не имеет никакого специального значения для интерпретатора Ruby. Однако, по соглашению, любой метод, имя которого заканчивается ? возвращает значение, которое отвечает на вопрос, заданные в вызове метода. Метод empty? массива, например, возвращает true, если у массива нет элементов. Большинство подобных методов возвращают одно из Булиановых значений true или false, но это не требуется, т.к. любое значение, отличное от false или nil работает как true, когда Булианово значение требуется. Числовой метод nonzero?, например, возвращает nil, если число его вызвано в нуле, в противном случае возвращает число.


Вывод

Я перечислил все важные пункты(здесь линку на след. статью), которые вы должны запомнить, после того, как вы закончите следующие темы: Scope (область видимости), Получение Input'a, Имена в Ruby, Больше о методах Ruby, Написание собственных методов Ruby.

Комментариев нет:

Отправить комментарий