Почему класс используется здесь вместе с const_get? - PullRequest
2 голосов
/ 13 сентября 2009
def self.get(server)
  return unless server
  server = server.to_s

  if klass = @handlers[server]
    obj = Object
    klass.split("::").each { |x| obj = obj.const_get(x) }
    obj
  else
    try_require('rack/handler', server)
    const_get(server)
  end
end

В коде выше const_get используется для получения некоторой именованной константы в этой строке:

    klass.split("::").each { |x| obj = obj.const_get(x) }

Если это так, почему «klass» особенно здесь используется? Я читал, что klass используется, чтобы избежать коллизий пространства имен с ключевым словом "class". Но в этом примере я не вижу, откуда может возникнуть возможный конфликт.

1 Ответ

5 голосов
/ 13 сентября 2009

Переменная называется klass, а не class, потому что и if class = @handlers[server], и class.split("::") вызовут синтаксическую ошибку, потому что, как вы сказали, class является ключевым словом в ruby.

Как правило, локальные переменные не могут быть названы как ключевые слова (методы хороши, но они могут вызываться только с явным получателем, поэтому вы не можете писать, например, class.name вместо self.class.name).

Каждый раз, когда анализатор видит токен class в начале выражения, он интерпретирует его как ключевое слово.

Редактировать: Чтобы уточнить: Проблема не в том, что использование класса здесь будет неоднозначным, а в том, что вы просто не можете использовать ключевые слова в качестве имен локальных переменных. Парсер не распознает их как таковые.

Редактировать в ответ на второй комментарий: klass используется здесь как локальная переменная, содержащая значение @handlers[server]. Код также может быть написан без переменной (при условии, что значение @handlers[server] не может измениться между двумя вызовами):

if @handlers[server]
    obj = Object
    @handlers[server].split("::").each { |x| obj = obj.const_get(x) }

Я предполагаю, что автор кода сохранил значение @handles[server] в переменной для a) не нужно набирать @handlers[server] дважды вместо одного раза, b) разъяснить читателю, что это значение является классом, и / или c) чтобы избежать необходимости звонить @handlers[] дважды.

YAEdit: Надеемся, что для устранения последней путаницы следующий код также эквивалентен:

if foo = @handlers[server]
  obj = Object
  foo.split("::").each { |x| obj = obj.const_get(x) }

Или:

foo = @handlers[server]
if foo
  obj = Object
  foo.split("::").each { |x| obj = obj.const_get(x) }

Однако klass является более описательным именем переменной, чем foo, поэтому (предположительно) автор решил назвать переменную klass.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...