Каковы прописные и строчные правила имени метода ruby?

Я начинающий Ruby. Из книги я знаю, что имя метода Ruby должно начинаться со строчной буквы или подчеркивания. Но я нашел разные сценарии:

  1. Если метод определен вне класса, он может начинаться только со строчной буквы, Ruby будет выдавать ошибку с ошибкой, если вы попытаетесь определить метод, который начинается с заглавной буквы, например:

    define sayHi
      puts "Hello" 
    end
    sayHi   # => Hello
    

    но следующий код не работает:

    define SayHi
      puts "Hello" 
    end
    SayHi 
    

    это выдаст ошибку:

    :in `<main>': uninitialized constant SayHi (NameError)
    
  2. Если метод определен внутри класса, он может начинаться с заглавной буквы:

    class Test
      def SayHi
        puts "hello" 
      end
    end
    t = Test.new
    t.SayHi    # => hello
    

Кто-нибудь знает, почему № 1 не работает, а № 2 работает? Каковы точные правила имени метода ruby?

2 ответа

Решение

По соглашению, вещи, которые начинаются с заглавных букв, являются константами. Когда вы вызываете SayHi, вы говорите Руби искать константу с этим именем. Конечно, его нет, поэтому он терпит неудачу.

Если вы хотите вызвать метод, вам нужно добавить пару скобок. Например,

def S
  puts "shazam!"
end

S    #=> NameError: uninitialized constant S
S()  #=> "shazam!"

Внутри класса правила разрешения немного отличаются. Давайте определим простой класс с константой и именем метода, который будет выглядеть как константа:

irb(main):001:0> class C
irb(main):002:1>   A = "x"
irb(main):003:1>   def B
irb(main):004:2>     puts "B() invoked"
irb(main):005:2>   end
irb(main):006:1> end
=> nil

Сейчас, A это конечно константа. Но что насчет B?

irb(main):008:0> C.const_defined?("A")
=> true    # A is a constant!
irb(main):009:0> C.const_defined?("B")
=> false   # B looks like a constant but isn't, because we
           # used "def" to create it. "def" is for methods,
           # not constants.

Так что это не константа, просто метод с таким именем. Когда мы пытаемся получить доступ B из экземпляра CСейчас Руби ищет метод:

irb(main):011:0> C.new.B
B() invoked
=> nil

Если бы мы хотели получить доступ к константе C вместо этого мы используем спецификатор области :::

irb(main):012:0> C::A
=> "x"

Не делай ничего из того, что ты пытаешься сделать. Это плохой стиль кодирования.

Хороший стиль кодирования Ruby:

def method_name
end

# or

class CamelCase
  def method_name(parameter_name)
  end
end

Почти все остальное просто неправильно. Язык может позволить вам делать другие вещи, но это не значит, что вы должны.

Кроме того, как правило, вы не хотите определять методы вне класса или модуля - это приемлемо в коротких одноразовых скриптах, но не в проектах по существу.

Другие вопросы по тегам