Это только часть разрешения неоднозначности Руби.
В 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 сводка: вы СОЛ.
То, что вы могли бы сделать, это переопределить 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
.
Я не знаю, как легко это решить.