Это всего лишь часть разрешения неоднозначности Ruby.
В Ruby методы и переменные живут в разных пространствах имен, поэтому могут быть методы и переменные (или константы) с одинаковыми именами. Это означает, что при их использовании должен быть какой-то способ их различать. В общем, это не проблема: у сообщений есть получатели, а у переменных нет. Сообщения имеют аргументы, а переменные — нет. Переменные назначаются, сообщения - нет.
Единственная проблема, когда у вас нет ни приемника, ни аргумента, ни присваивания. Затем Ruby не может отличить сообщение без получателя, отправляемое без аргументов, и переменную. Таким образом, он должен составить некоторые произвольные правила, и эти правила в основном таковы:
- неоднозначный токен, начинающийся со строчной буквы, лучше интерпретировать как отправку сообщения, если вы точно не знаете, что это переменная (т. е. парсер (не(!) переводчик) уже видел задание раньше)
- для неоднозначного токена, начинающегося с заглавной буквы, предпочтительнее интерпретировать его как константу
Обратите внимание, что для сообщения, отправленного с аргументами (даже если список аргументов пуст), двусмысленности нет, поэтому ваш третий пример работает.
test()
: явно отправлено сообщение, здесь нет двусмысленности
test
: может быть отправкой сообщения или переменной; правила разрешения говорят, что это сообщение отправлено
Test()
: очевидно, сообщение отправлено, здесь нет никакой двусмысленности
self.Test
: тоже очевидно, сообщение отправлено, здесь нет двусмысленности
Test
: может быть отправкой сообщения или константой; правила разрешения говорят, что это константа
Обратите внимание, что эти правила немного тонкие, например здесь:
if false
foo = 'This will never get executed'
end
foo # still this will get interpreted as a variable
В правилах говорится, что то, интерпретируется ли неоднозначный токен как переменная или отправка сообщения, определяется парсером, а не интерпретатором. Итак, поскольку синтаксический анализатор увидел foo = whatever
, он помечает foo
как переменную, хотя код никогда не будет выполнен, а foo
будет оцениваться как nil
, как это делают все неинициализированные переменные в Ruby.
TL; DR резюме: вы SOL.
Что вы могли сделать, так это переопределить const_missing
, чтобы преобразовать его в отправку сообщения. Что-то вроде этого:
class DemoClass
def test; puts "output from test" end
def Test; puts "output from Test" end
def run
puts "Calling 'test'"
test()
puts "Calling 'test'"
test
puts "Calling 'Test()'"
Test()
puts "Calling 'Test'"
Test
end
def self.const_missing(const)
send const.downcase
end
end
demo = DemoClass.new
demo.run
За исключением того, что это, очевидно, не сработает, поскольку const_missing
определено для DemoClass
и, таким образом, когда const_missing
запускается, self
является DemoClass
, что означает, что он пытается вызвать DemoClass.test
, когда он должен вызывать DemoClass#test
через demo.test
.
Я не знаю, как легко это решить.
person
Jörg W Mittag
schedule
01.06.2010