Ruby, что означают такие выражения?
От: megas  
Дата: 11.10.09 13:41
Оценка:
Не могу понять смысла таких выражений с использованием оператора '<<'

1.
class Something
class << self; attr_reader :generated_classes; end
end
Какую функцию здесь выполняет оператор '<<' ?

2.
class SomethingElse
@generated_classes << klass = Object.const_set(class_name, Class.new(PoorMan))
end
Здесь вроде объявляется член класса и к нему добавляется элемент массива?

Спасибо
Re: Ruby, что означают такие выражения?
От: Гест Украина https://zverok.github.io
Дата: 11.10.09 14:11
Оценка: 4 (3) +1
Здравствуйте, 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
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.