format
что-то вроде
class API
private_class_method def self.format(kind)
#...
end
end
частных методов в Ruby, не может быть вызван с явным приемником (с точкой перед ними), только неявные один (отсылка к текущему значению self
). Внутри определения класса self
определяется классом. Именно поэтому вы можете написать
def self.format(...)
вместо
def API.format(...)
Таким образом, в вашем коде,
class MyAPI < API
format :json
# ...
end
это вызов метода format
на объект класса MyAPI
, в силу наследование от API
, как класс определяется. Если посмотреть на источник Grape, format
будет (в конечном итоге) установить значение в переменной экземпляра. Давайте упростим его до @format
(на самом деле это не так, и оно унаследовано, а не на API
, но ... упрощение для примера). Давайте также сделаем другой метод, чтобы увидеть, что такое значение переменной экземпляра.
class API
private_class_method def self.format(what)
@format = what
end
def self.peek_format
@format
end
end
Теперь давайте создадим подкласс:
class SubAPI < API
end
Теперь, чтобы установить формат, мы хотели бы использовать что-то вроде API.format(:json)
, но мы не можем, потому что это личное. Таким образом, мы произведем контекст, в котором format(:json)
естественно переходит к API
:
class API
format :json
end
API.peek_format
# => :json
Формат устанавливается. Все выглядит хорошо. Теперь давайте посмотрим, что происходит с подклассом:
class SubAPI
format :txt
end
SubAPI.peek_format
# => :txt
Но
API.peek_format
# => :json
методы наследуются; переменные экземпляра нет. Каждый экземпляр класса (т. Е. Объект типа Class
) имеет свой собственный набор переменных экземпляра, так же как каждый другой объект имеет свой собственный набор переменных экземпляра, не разделяемый с другими объектами одного и того же класса.
Если вы действительно хотите каждый подкласс, чтобы сделать то же инициализации, вы можете сделать что-то вроде этого (хотя это не лучшая идея):
class API
private_class_method def self.format(what)
@format = what
end
def self.peek_format
@format
end
# common initialisation
private_class_method def self.initialize_class
format :json
end
# whenever we get a new subclass, run the initialisation
private_class_method def self.inherited(subclass)
subclass.instance_eval do
initialize_class
end
end
# now initialise this class too
initialize_class
end
class SubAPI < API
end
API.peek_format
# => :json
SubAPI.peek_format
# => :json
Но я призываю вас против этого. Если вы используете MyAPI
, то вы, вероятно, не используете API
; вам не нужно устанавливать в нем формат (или другие параметры).
Это вызовы методов, которые, вероятно, устанавливают некоторые атрибуты. Что вы подразумеваете под «в том, что класс« MyAPI »' format', 'prefix' и' version' не работает?? Они не приносят никакой ошибки, они совершенно юридический код. Продемонстрируйте, как именно они не работают (с кодом и сообщением об ошибке или нежелательным поведением, проявленным этим кодом). – Amadan
Parenthesis являются необязательными, поэтому 'format (: json)' такой же, как 'format: json'. –
@Amadan Например, 'format' устанавливает для api вывод результата в формате json. В классе Twitter :: API он работает хорошо, но в дочернем случае он просто не применяется. – Yaroslav