Skip to content

Latest commit

 

History

History
139 lines (99 loc) · 7.28 KB

methods.md

File metadata and controls

139 lines (99 loc) · 7.28 KB

Методи

TODO: връщане на стойности? Къде да се вмъкне? По-добър пример?
TODO: повече за класове? Отделна статия?
TODO: внимание при monkey-patching
TODO: липса на скоби

TODO: това трябва да се изговори на живо и да се реши доколко тия неща са разбираеми. След това вероятно ще трябва да се пренапише с feedback-а от живите сесии.

"Метод" е термин, който често може да се замести с "действие". Накратко, това е парче код, което си има някакво име, и може да се изпълни на друго място чрез това име.

Един прост пример:

def say_hello
  puts "Hello!"
  puts "It's such a wonderful day, isn't it?"
end

Този код дефинира метод с името say_hello, който при изпълнение извежда на екрана два реда текст. Изпълнението на метода става просто с именуването му:

say_hello

Това е прост начин за преизползване на код. Ако искаме да напишем някаква сложна логика на две различни места, можем да я сложим в метод и да я извикваме и на двете места с по един ред.

Параметри

Рядко обаче имаме съвсем същата логика на две места. Обикновено тя се различава по някакви малки начини. Примерно, ако искаме метода say_hello да поздрави някого по име, трябва това име да дойде отнякъде. Това става с параметри:

def say_hello(name, adjective)
  puts "Hello, #{name}!"
  puts "It's such a #{adjective} day, isn't it?"
end

В скоби слагаме параметрите на метода, разделени със запетаи. В случая имаме два: name за името, което поздравяваме и adjective за прилателното, което използваме за деня. По този начин, можем да изпълним следния код:

say_hello("John", "wonderful")
say_hello("Jane", "beautiful")

При изпълнение на тези два реда ще се изведе:

Hello, John!
It's such a wonderful day, isn't it?
Hello, Jane!
It's such a beautiful day, isn't it?

Така можем да пишем доста сложни методи, които използват параметрите си за да решат какво точно да направят.

"Методи" и "функции"

Въпреки, че ги наричаме "методи", в доста други езици тези парчета код биха били наричани "функции". Разликата е, че "методи" се извикват върху някакъв обект. В случая, когато дефинираме say_hello, просто го дефинираме върху глобалния обект. За да демонстрираме пълната употреба на метод с получател-обект, нека видим следния пример:

me = "John"

def me.say_hello_to(other_person)
  puts "Hello, #{other_person}, my name is #{self}."
end

me.say_hello_to("Jane")
me.say_hello_to("Sally")

Изпълнението на този код ще доведе до:

Hello, Jane, my name is John.
Hello, Sally, my name is John.

Забележете, че дефинираме метода със def me.say_hello_to. Тоест, вземаме обекта, към който сочи me (който в случая е низа "John"), и добавяме метод върху него. По този начин този обект вече има способността да поздравява когото и да е. В рамките на дефиницията на метода (между реда с def и реда с end), променливата self има стойността на точно този обект. Така можем да го използваме в поздрава.

Класове

Това обаче работи само върху точно този обект -- точно този низ "John". Ако след това извикаме просто "John".say_hello_to("Sally"), ще получим грешка.

Ако искаме всички низове да имат способността да поздравяват, ще трябва да опишем, че всички низове някога създадени вече имат този метод дефиниран върху тях. Това става като отворим класа String:

class String
  def say_hello_to(other_person)
    puts "Hello, #{other_person}, my name is #{self}."
  end
end

Класът е нещо като схематика на обект. Той описва какви методи ще има обект, създаден през него. Класът String описва всички низове, които някога създадем. С този код получаваме възможността да кажем:

"John".say_hello_to("Sally")
"Sally".say_hello_to("Jane")

Полезен пример

Списъците имат метод, който се казва include?. Той се използва по следния начин:

user_choice = gets.chomp

if ["rock", "paper", "scissors"].include? user_choice
  puts "Valid move"
else
  puts "Invalid move"
end

Израза ["rock", "paper", "scissors"].include? user_choice обаче е малко тромав. Вместо да попитаме "Намира ли се избора на потребителя в ето този списък?", използваме "Този списък съдържа ли избора на потребителя?". За много хора това не е толкова интиутивно като словоред. Така че ще се опитаме да обърнем нещата.

class Object
  def in?(list)
    list.include?(self)
  end
end

Първо, отваряме класа Object. Той е базовия клас, който е схематика на всички обекти в системата. След това, дефинираме метод in?, който просто приема списък и връща резултата от изпълнението на метода include? върху него. Крайния резултат е, че вече можем да напишем следното:

user_choice = gets.chomp

if user_choice.in? ["rock", "paper", "scissors"]
  puts "Valid move"
else
  puts "Invalid move"
end

Което се чете малко по-приятно.