#ruby
#ruby
Вопрос:
Я читаю Stripe API и вижу это:
module Stripe
...
class << self
attr_accessor :stripe_account, :api_key, :api_base, :verify_ssl_certs, :api_version, :connect_base, :uploads_base,
:open_timeout, :read_timeout
attr_reader :max_network_retry_delay, :initial_network_retry_delay
end
Что там происходит? Я пытался прочитать блог Иегуды Каца об этом, но некоторые его части неясны, например:
Что происходит в двух примерах, которые он предоставляет?
Оказывается, что все эти странные правила сводятся к одной концепции: контроль над self в данной части кода. Давайте вернемся назад и взглянем на некоторые фрагменты, которые мы рассмотрели ранее:
class Person
def name
"Matz"
end
self.name #=> "Person"
end
Здесь мы добавляем метод name
в класс Person . Как только мы скажемclass Person
, self до конца
блока — это самPerson
класс.
Person.class_eval do
def name
"Matz"
end
self.name #=> "Person"
end
Здесь мы делаем то же
самое: добавляем метод name к экземплярамPerson
класса. В
этом случаеclass_eval
устанавливается значение self для Person до конца
блока. Все это совершенно прямолинейно при работе с
классами, но не менее прямолинейно и при работе с
метаклассами:
Почему Иегуда продолжает писать:
self.name #=> "Person"
Ответ №1:
В Ruby нет такого понятия, как «метод класса». Все методы являются методами экземпляра. Дело в том, что экземпляры разные.
Stripe
является экземпляром class Module
и Person
является экземпляром class Class
.
Итак, в вашем первом примере ( Stripe
) есть определение attr_accessor
s, доступное для object Stripe
.
Таким образом, вы сможете читать и записывать Stripe
атрибуты s:
Stripe.api_key = :some_key
Stripe.api_key
#=> :some_key
В то время как следующий определяет метод, доступный экземплярам класса Person
Person.class_eval do
def name
"Matz"
end
end
Вы могли бы определить метод экземпляра, доступный для Person
класса с помощью using instance_eval
, который оценивал код в контексте получателя:
Person.instance_eval do
def name
"Matz"
end
end
Person.name # this is what they sometimes called "a class method", which I don't like personally
#=> 'Matz'
Это всегда просто вопрос контекста. Как только вы поймете, что self
есть и куда self
указывает в любой момент — все станет намного понятнее.
Комментарии:
1. @Jwan622 потому что это контекст
Person
. Как я уже сказал, это всегда вопросself
. Внутри тела класса вы находитесь в контексте этого класса, что означает, чтоself
указывает на сам класс. Это то же самое, как если бы вы писалиPerson.name
вне определения класса2.
name
похоже, это встроенная функция.3. @Jwan622 вот документы для
name
метода