Ruby: NoMethodError, but why?

旧城冷巷雨未停 提交于 2019-12-03 07:09:35
Arup Rakshit

You have defined an instance method and are trying to call it as a method of a class. Thus you need to make the method hello a class method, not an instance method of the class Methods.

class Methods
  def self.hello(player)
    print "Hello, " << player
  end
  hello("Annie")
end

Or, if you want to define it as instance method then call it as below :

class Methods
  def hello(player)
    print "Hello, " << player
  end
end
Methods.new.hello("Annie")

You're trying to call an instance method as a class method.

Here's some code that illustrates the difference between the two in ruby:

class Person

  # This is a class method - note it's prefixed by self
  # (which in this context refers to the Person class)
  def self.species
    puts 'Human'
    # Note: species is OK as a class method because it's the same 
    # for all instances of the person class - ie, 'Bob', 'Mary', 
    # 'Peggy-Sue', and whoever else, are ALL Human.
  end

  # The methods below aren't prefixed with self., and are
  # therefore instance methods

  # This is the construct, called automatically when
  # a new object is created
  def initialize(name)
    # @name is an instance variable
    @name = name
  end

  def say_hello
    puts "Hello from #{@name}"
  end

end

And now try it out, calling the methods...

# Call a class method...
# We're not referring to any one 'instance' of Person,
Person.species #=> 'Human'

# Create an instance
bob = Person.new('Bob')

# Call a method on the 'Bob' instance
bob.say_hello #=> 'Hello from Bob'

# Call a method on the Person class, going through the bob instance
bob.class.species #=> 'Human'

# Try to call the class method directly on the instance
bob.species #=> NoMethodError

# Try to call the instance method on the class
# (this is the error you are getting)
Person.say_hello #=> NoMethodError
Sara Tibbetts

You've created an instance method, but you're calling a class method. In order to call hello("Annie"), you have to make an instance of Methods. For instance:

class Methods
  def self.hello(player)
      print "Hello, " << player
  end
end

my_method = Methods.new
my_method.hello("Annie")

This would output Hello, Annie

By defining a method with def method_name args you are defining a instance method that will be included in every object of that class, but not in the class itself.

On the other hand, by def self.method_name args you will get a class method that will be directly in the class, without the need of instanciate an object from it.

So If you have this:

Class Test
   def self.bar
   end

   def foo
   end

end

You can execute the instance method this way:

a = Test.new
a.foo

And as for the class one should be:

Test.foo
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!