Здравствуйте, megas, Вы писали:
M>Не могу понять смысла таких выражений с использованием оператора '<<'
в обоих случаях оператор выполняет принципиально разную роль, к сожалению.
Случай 1 — определение класса «только этого объекта».
Например:
x = "test"
class << x
def x.test
puts "ok"
end
end
#теперь x будет вести себя как строка, только с ещё одни методом test
x.test #печатает ok
"other string".test #любая другая строка по-прежнему ругается на отсутвие такого метода
теперь, что происходит, когда мы используем этот трюк во время определения класса
class Something
class << self #в этом контексте self — это сам класс Something, т.е.
#мы определяем здесь «класс класса Something» — «метакласс»
attr_reader :generated_classes
end
#после выполнения этого кода у ОБЪЕКТА Something есть метод generated_classes. его можно использовать прямо здесь:
if generated_classes ....
end
# или позже:
Something.generated_classes ...
Случай 2 — сам оператор выполняет простую роль, но вот выражение в целом довольно сложное:
class SomethingElse
@generated_classes << klass = Object.const_set(class_name, Class.new(PoorMan))
end
Конкретный оператор << здесь всего лишь добавляет ещё один член в массив generated_classes. Всё выражение в целом надо читать так: в переменную экземпляра @generated_classes (являющуюся массивом) добавить новый член. этим член будет новый класс, унаследованный от класса PoorMan (выражение «Class.new(PoorMan)»). Заодно этот класс станет доступным в глобальом пространстве имён по имени, хранящемся в переменной class_name (выражение «Object.const_set(class_name, ....)»; а так же будет сохранён в локальной переменной klass (выражение «klass= ...»; видимо, где-то ниже по коду она будет использоваться).
Выражение можно переписать так:
class SomethingElse
klass = Class.new(PoorMan) #создали новый класс
Object.const_set(class_name, klass) #запихнули его в глобальное пространство имён
@generated_classes << klass #забросили в массив
end