2016-10-06 6 views
2

Я пытаюсь лучше понять правила Ruby и как получить доступ к метаклассу. Я читаю статью Иегуды Каца на метапрограммировании, и я наткнулся на это:Получение доступа к метаклассу в Ruby

matz = Object.new 
def matz.speak 
    "Place your burden to machine's shoulders" 
end 

matz.class #=> Object 

В самом деле, «класс» Мац является его невидимым метаклассом. Мы можем даже получить доступ к метаклассу:

metaclass = class << matz; self; end 
metaclass.instance_methods.grep(/speak/) #=> ["speak"] 

Что происходит на этой линии:

metaclass = class << matz; self; end 

Это то же самое, как:

matz 
    self 
end 

?

+0

примечание: 'matz.singleton_methods # => [: speak] ' –

+1

Я смущен тем, что метод [Object # singleton_class] (http://ruby-doc.org/core-2.3.0/Object.html#method-i-singleton_class) является не используется больше. Это позволяет нам написать 'metaclass = matz.singleton_class'. Я думаю, вы согласитесь, что это более читаемо, чем 'metaclass = class << matz; самостоятельно; end'. –

ответ

2

Что происходит на этой линии:

metaclass = class << matz; self; end 
class << foo 

открывает класс одноплодной из foo. Внутри тела определения класса, self - это класс. Возвращаемое значение тела определения класса - это значение последнего выражения внутри тела определения класса.

Таким образом, мы назначаем значение тела определения класса, которое является значением последнего выражения внутри тела определения класса, которое равно self, которое является классом, то есть одноэлементным классом matz.

Другими словами: мы присваиваем одиночный класс matz локальной переменной metaclass.

Обратите внимание, что для современного Ruby используется метод Object#singleton_class (добавленный в Ruby 1.9.2, выпущенный в 2010 году).

Это то же самое, как:

matz 
    self 
end 

Очевидно, что нет, так как первый является законным синтаксис, и это не так.

1

class << matz; self; end эквивалентно

class << mats 
    self 
end 

class << matz; end открывает класс одноплодной (рубин официальное название метакласса). Это также выражение, возвращающее возвращаемое значение последнего выражения, которое оценивается внутри него, в этом случае self.

Я думаю, вы знакомы с self, так как играете с метапрограммированием. self относится к самому классу, когда он входит в сферу действия класса, в вашем коде он относится к классу singleton.

P.S. начинается с Ruby 1.9.2, нет необходимости использовать этот синтаксис лопаты, чтобы захватить одноэлементный класс. Только obj.singleton_class.