Хэл Фултон - Программирование на языке Ruby
- Название:Программирование на языке Ruby
- Автор:
- Жанр:
- Издательство:ДМК Пресс
- Год:2007
- Город:Москва
- ISBN:5-94074-357-9
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Хэл Фултон - Программирование на языке Ruby краткое содержание
Ruby — относительно новый объектно-ориентированный язык, разработанный Юкихиро Мацумото в 1995 году и позаимствовавший некоторые особенности у языков LISP, Smalltalk, Perl, CLU и других. Язык активно развивается и применяется в самых разных областях: от системного администрирования до разработки сложных динамических сайтов.
Книга является полноценным руководством по Ruby — ее можно использовать и как учебник, и как справочник, и как сборник ответов на вопросы типа «как сделать то или иное в Ruby». В ней приведено свыше 400 примеров, разбитых по различным аспектам программирования, и к которым автор дает обстоятельные комментарии.
Издание предназначено для программистов самого широкого круга и самой разной квалификации, желающих научиться качественно и профессионально работать на Ruby.
Программирование на языке Ruby - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
11.2.2. Специализация отдельного объекта
Я солипсист и, признаться, удивлен, что большинство из нас таковыми не являются.
Из письма, полученного Бертраном РасселомВ большинстве объектно-ориентированных языков все объекты одного класса ведут себя одинаково. Класс — это шаблон, порождающий объекты с одним и тем же интерфейсом при каждом вызове конструктора.
Ruby ведет себя так же, но это не конец истории. Получив объект, вы можете изменить его поведение на лету. По сути дела, вы ассоциируете с объектом частный, анонимный подкласс, все методы исходного подкласса остаются доступными, но добавляется еще и поведение, уникальное для данного объекта. Поскольку это поведение присуще лишь данному объекту, оно встречается только один раз. Нечто, встречающееся только один раз, называется синглетом (singleton). Так, мы имеем синглетные методы и синглетные классы.
Слово «синглет» может стать источником путаницы, потому что оно употребляется и в другом смысле - как название хорошо известного паттерна проектирования, описывающего класс, для которого может существовать лишь один объект. Если вас интересует такое использование, обратитесь к библиотеке singleton.rb
.
В следующем примере мы видим два объекта, оба строки. Для второго мы добавляем метод upcase
, который переопределяет существующий метод с таким же именем.
а = "hello"
b = "goodbye"
def b.upcase # Создать синглетный метод.
gsub(/(.)(.)/) { $1.upcase + $2 }
end
puts a.upcase # HELLO
puts b.upcase # GoOdBye
Добавление синглетного метода к объекту порождает синглетный класс для данного объекта, если он еще не был создан ранее. Родителем синглетного класса является исходный класс объекта. (Можно считать, что это анонимный подкласс исходного класса.) Если вы хотите добавить к объекту несколько методов, то можете создать синглетный класс явно:
b = "goodbye"
class << b
def upcase # Создать синглетный метод.
gsub(/(.){.)/) { $1.upcase + $2 }
end
def upcase!
gsub!(/(.)(.)/) { $1.upcase + $2 }
end
end
puts b.upcase # GoOdBye
puts b # goodbye
b.upcase!
puts b # GoOdBye
Отметим попутно, что у более «примитивных» объектов (например, Fixnum
) не может быть добавленных синглетных методов. Связано это с тем, что такие объекты хранятся как непосредственные значения, а не как ссылки. Впрочем, реализация подобной функциональности планируется в будущих версиях Ruby (хотя непосредственные значения сохранятся).
Если вам приходилось разбираться в коде библиотек, то наверняка вы сталкивались с идиоматическим использованием синглетных классов. В определении класса иногда встречается такой код:
class SomeClass
# Stuff...
class << self
# Какой-то код
end
# ...продолжение.
end
В теле определения класса слово self
обозначает сам определяемый класс, поэтому создание наследующего ему синглета модифицирует класс этого класса. Можно сказать, что методы экземпляра синглетного класса извне выглядят как методы самого класса.
class TheClass
class << self
def hello
puts "hi"
end
end
end
# вызвать метод класса
TheClass.hello # hi
Еще одно распространенное применение такой техники — определение на уровне класса вспомогательных функций, к которым можно обращаться из других мест внутри определения класса. Например, мы хотим определить несколько функций доступа, которые преобразуют результат своей работы в строку. Можно, конечно, написать отдельно код каждой такой функции. Но есть и более элегантное решение — определить функцию уровня класса accessor_string
, которая сгенерирует необходимые нам функции (как показано в листинге 11.10).
сlass MyClass
class << self
def accessor_string(*names)
names.each do |name|
class_eval <<-EOF
def #{name}
@#{name}.to_s
end
EOF
end
end
end
def initialize
@a = [1,2,3]
@b = Time.now
end
accessor_string :a, :b
end
о = MyClass.new
puts o.a # 123
puts o.b # Mon Apr 30 23:12:15 CDT 2001
Вы наверняка сможете придумать и другие, более изобретательные применения. Метод extend
подмешивает к объекту модуль. Методы экземпляра, определенные в модуле, становятся методами экземпляра объекта. Взгляните на листинг 11.11.
module Quantifier
def any?
self.each { |x| return true if yield x }
false
end
def all?
self.each { |x| return false if not yield x }
true
end
end
list = [1, 2, 3, 4, 5]
list.extend(Quantifier)
flag1 = list.any? {|x| x > 5 } # false
flag2 = list.any? {|x| x >= 5 } # true
flag3 = list.all? {|x| x <= 10 } # true
flag4 = list.all? {|x| x % 2 == 0 } # false
В этом примере к массиву list
подмешаны методы any?
и all?
.
11.2.3. Вложенные классы и модули
Классы и модули можно вкладывать друг в друга произвольным образом. Программисты, приступающие к изучению Ruby, могут этого и не знать.
Основная цель данного механизма — упростить управление пространствами имен. Скажем, в класс File
вложен класс Stat
. Это помогает «инкапсулировать» класс Stat
внутри тесно связанного с ним класса, а заодно оставляет возможность в будущем определить класс Stat
, не конфликтуя с существующим (скажем, для сбора статистики).
Другой пример дает класс Struct::Tms
. Любая новая структура Struct
помещается в это пространство имен, не «загрязняя» расположенные выше, a Tms
— в действительности тоже Struct
.
Кроме того, вложенный класс можно создавать просто потому, что внешний мир не должен знать о нем или обращаться к нему. Иными словами, можно создавать целые классы, подчиняющиеся тому же принципу «сокрытия данных», которому переменные и методы экземпляра следуют на более низком уровне.
class BugTrackingSystem
class Bug
#...
end
#...
end
# Никто снаружи не знает о классе Bug.
Можно вкладывать класс в модуль, модуль в класс и т.д. Если вы придумаете интересные и изобретательные способы применения этой техники, дайте нам знать.
11.2.4. Создание параметрических классов
Изучи правила, потом нарушай их.
БасёПредположим, что нужно создать несколько классов, отличающихся только начальными значениями переменных уровня класса. Напомним, что переменная класса обычно инициализируется в самом определении класса.
class Terran
@@home_planet = "Earth"
Интервал:
Закладка: