Чтение онлайн

на главную - закладки

Жанры

Программирование на языке Ruby
Шрифт:

 def initialize(name, age, height)

@name, @age, @height = name, age, height

 end

 def inspect

"#@name #@age #@height"

 end

end

class Array

 def sort_by(sym) # Наш вариант метода sort_by.

self.sort {|x,y| x.send(sym) <=> y.send(sym) }

 end

end

people = []

people << Person.new("Hansel", 35, 69)

people << Person.new("Gretel", 32, 64)

people << Person.new("Ted", 36, 68)

people << Person.new("Alice", 33, 63)

p1 = people.sort_by(:name)

p2 = people.sort_by(:age)

p3 = people.sort_by(:height)

p p1 # [Alice 33 63, Gretel 32 64, Hansel 35 69, Ted 36 68]

p p2 # [Gretel 32 64, Alice 33 63, Hansel 35 69, Ted 36 68]

p p3 # [Alice 33 63, Gretel 32 64, Ted 36 68, Hansel 35 69]

Отметим

еще, что синоним
__send__
делает в точности то же самое. Такое странное имя объясняется, вероятно, опасением, что имя
send
уже может быть задействовано (случайно или намеренно) для определенного пользователем метода.

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).

Поделиться:
Популярные книги

Газлайтер. Том 22

Володин Григорий Григорьевич
22. История Телепата
Фантастика:
боевая фантастика
попаданцы
фэнтези
5.00
рейтинг книги
Газлайтер. Том 22

Тринадцатый IV

NikL
4. Видящий смерть
Фантастика:
боевая фантастика
попаданцы
5.00
рейтинг книги
Тринадцатый IV

Древесный маг Орловского княжества 5

Павлов Игорь Васильевич
5. Орловское княжество
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Древесный маг Орловского княжества 5

Я до сих пор не князь. Книга XVI

Дрейк Сириус
16. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я до сих пор не князь. Книга XVI

Черный дембель. Часть 4

Федин Андрей Анатольевич
4. Черный дембель
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Черный дембель. Часть 4

"Дальние горизонты. Дух". Компиляция. Книги 1-25

Усманов Хайдарали
Собрание сочинений
Фантастика:
фэнтези
боевая фантастика
попаданцы
5.00
рейтинг книги
Дальние горизонты. Дух. Компиляция. Книги 1-25

Глубокий космос

Вайс Александр
9. Фронтир
Фантастика:
боевая фантастика
космическая фантастика
космоопера
5.00
рейтинг книги
Глубокий космос

Первый среди равных. Книга IX

Бор Жорж
9. Первый среди Равных
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Первый среди равных. Книга IX

Обгоняя время

Иванов Дмитрий
13. Девяностые
Фантастика:
попаданцы
5.00
рейтинг книги
Обгоняя время

Воронцов. Перезагрузка. Книга 2

Тарасов Ник
2. Воронцов. Перезагрузка
Фантастика:
попаданцы
альтернативная история
фэнтези
5.00
рейтинг книги
Воронцов. Перезагрузка. Книга 2

Источники силы

Amazerak
4. Иной в голове
Фантастика:
боевая фантастика
рпг
аниме
5.00
рейтинг книги
Источники силы

Железный Воин Империи

Зот Бакалавр
1. Железный Воин Империи
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Железный Воин Империи

Адвокат Империи 4

Карелин Сергей Витальевич
4. Адвокат империи
Фантастика:
городское фэнтези
аниме
дорама
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Адвокат Империи 4

Контртеррор

Валериев Игорь
6. Ермак
Фантастика:
альтернативная история
5.00
рейтинг книги
Контртеррор