Ruby/Подробнее о методах: различия между версиями

Содержимое удалено Содержимое добавлено
Базы данных для продвинутых предпринимателей
м Откат правок 188.162.9.158 (обс.) к версии 193.138.246.170
Строка 417:
=== Способы расширения библиотеки методов ===
 
==== Как добавить метод к массиву/строке/венику? ====
Соберем для Вас по сети интернет
 
базу данных потенциальных клиентов для Вашего Бизнеса
Важно помнить, что в Ruby все типы являются обьектами, даже сами классы. Каждый класс до конца выполнения программы остаётся открытым, а это значит, что в любой тип можно добавить собственные методы (или изменить поведение существующих). Каждый класс можно определять постепенно, в нескольких частях программы:
(все контактные данные - название, телефон, факс, имена, рода деятельности,
 
email и др)
<source lang="ruby">class Broom
Более подробно узнайте по телефону:+79133913837
def sweep
По e-mail: prodawez@mixmail.com
end
По ICQ: 6288862
end
По Skype: s....8
 
Broom.instance_methods #=> […, "sweep", …]
 
class Broom
def wash_lavatory_pan(lavatory_pan)
end
end
 
Broom.instance_methods #=> […, "sweep", …, "wash_lavatory_pan", …]</source>
 
Метод <code>.instance_methods</code> возвращает массив, который содержит имена методов, которые можно вызвать.
 
Добавленные методы становятся доступны немедленно, в том числе для уже созданнных экземпляров типа. Стоит помнить, что методы в Ruby — на самом деле «сообщения», и у каждого метода есть «приёмник», то есть объект, которому сообщение отправлено. Метод по умолчанию ищет другие методы в экземпляре класса, поскольку приёмником для него является <code>self</code>.
 
Простейший пример — добавление метода классу <code>String</code>, выводящий только согласные буквы из строки:
 
<source lang="ruby">class String
def consonants
cons = []
self.scan(/[BCDFGHJKLMNPRSTVWXZbcdfghjklmnprstvwxz]/){ |m| cons << m }
cons.uniq.join
end
end
 
"Crazy brown fox jumps over a lazy dog".consonants #=> "Crzbwnfxjmpsvrldg"</source>
 
Операция расширения класса (добавление нового метода к существующему) по сути не отличается от создания нового класса.
 
У обьектов в Ruby есть методы класса и методы экземпляра. В нашем примере <code>consonants</code> — это именно метод экземпляра. При создании нового класса или изменении существующего создать метод класса можно, начав его имя с имени класса или с <code>self</code> и точки:
 
<source lang="ruby">class String
def self.consonants_from(string)
cons = []
string.scan(/[BCDFGHJKLMNPRSTVWXZbcdfghjklmnprstvwxz]/){ |m| cons << m }
cons.uniq.join
end
end
 
String.consonants_from("Crazy fox jumps over a lazy dog") #=> "Crzbwnfxjmpsvldg"</source>
 
Одним из специфических свойств Ruby является то, что классы сами по себе — экземпляры класса <code>Class</code>, и с ними можно работать как с обычными объектами. Специальный синтаксис для доступа к методам класса в Ruby не нужен. Классы можно хранить в переменных, передавать методам и так далее.
 
В контексте класса <code>self</code> — это сам класс.
 
Проиллюстрируем это простым примером. Как мы знаем, у класса <code>File</code> есть метод <code>open</code>. Создадим метод у класса <code>File</code>, дающий нам доступ к временному файлу, создаваемому в момент выполнения кода. Это такой же метод, но открывающий только файлы из директории <code>/tmp</code>:
 
<source lang="ruby">
class File
def self.temporary(&closure)
# определим директорию, в которой в данный момент запущена программа
# методы dirname и expand_path в данном случае — File.dirname и File.expand_path
dirname = self.dirname(self.expand_path(__FILE__))
base = basename(__FILE__, '.rb') #=> имя файла с программой без расширения .rb
stamp = "#{base}_#{Time.now.to_i}.tmp" #=> системное время в секундах и расширение .tmp
 
# File.join соединит фрагменты пути обратным слешем в Windows и прямым слешем на UNIX
path = join(dirname, stamp)
self.open(path, 'w', &closure)
end
end
 
File.temporary { |f| f << "Some info" } #=> #<File:/Tests/(irb)_1151198720.tmp (closed)></source>
 
{{info|Для управления временными файлами в Ruby существует класс <code>Tempfile</code>. Помимо других достоинств он гарантирует, что созданные временные файлы по завершении программы
будут удалены.}}
 
Если к классу надо добавить много методов сразу, то при описании класса можно выйти на уровень его обьекта-класса. Это свойство в Ruby называется ''eigenclass'' ({{нем|eigen}} — свой, особый). Подозревая, что многие из читателей незнакомы с математическим понятием [[w:Собственные вектора, значения и пространства|собственного значения/вектора/пространства]], мы кратко и по-программистски назовём eigenclass ''айгенклассом''. Аналогичные концепции в других языках, например в Smalltalk, от которого Ruby наследовал свою объкетную идеологию, называются также ''метаклассами''.
 
Добавим к классу <code>File</code> метод <code>myself</code>, который даёт быстрый доступ к текущему файлу с исходным кодом:
 
<source lang="ruby">class Manager
class << self
def create
end
 
def manage
end
end
end</source>
 
Если нужно добавить метод только к конкретному экземпляру, нужно выйти на его айгенкласс:
 
<source lang="ruby">
string = "Crazy brown fox jumps over a lazy dog"
other_string = "Three black witches"
 
def string.vowels
vowels = []
scan(/[AEIOUYaeiuoy]/){ |m| vowels << m}
vowels.uniq.join
end
 
string.vowels #=> "ayoue"
other_string.vowels #=> NoMethodError: undefined method `vowels' for …</source>
 
Возможность добавлять и изменять устройство уже существующих классов — одно из основных свойств Ruby, обеспечивающих великую гибкость языка. Часто бывает, что метод возвращает не тот результат, который нам нужен — тогда при его изменении все программы, обращающиеся к данному методу будут получать изменённый результат.
 
==== Программист-разрушитель ====