Подтвердить что ты не робот

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

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

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

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

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

    define SayHi
      puts "Hello" 
    end
    SayHi 
    

    он выдает ошибку:

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

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

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

4b9b3361

Ответ 1

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

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

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, теперь Ruby ищет метод:

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

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

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

Ответ 2

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

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

def method_name
end

# or

class CamelCase
  def method_name(parameter_name)
  end
end

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

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