I'm just startin to learn ruby and I'm writing a simple program, but I've got an error undefined method 'send_for_beer' for Person:Class (NoMethodError)
Here is a code:
class Person
@iq = 0
@speed = 0
@power = 0
@beauty = 0
def initialize (iq, speed, power, beauty)
@iq = iq
@speed = speed
@power = power
end
def send_for_beer
result @iq * 2 + @speed * 10 + @power * 5 + @beauty
return result
end
end
number_of_people = 3
person_array = Array.new(number_of_people, Person)
n = 0
beer_person = 0
beer_cof = 0
number_of_people.times do
............
person_array.push(Person.new(iq, speed, power, beauty))
if person_array[n].send_for_beer > beer_cof <-----here is an error
beer_cof = person_array[n].send_for_beer
beer_person = n
end
n = n+1
end
Here's your problem:
person_array = Array.new(number_of_people, Person)
In short, don't make array like this. Use the []
literal syntax. What this returns is:
[Person, Person, Person]
That is 3 references to the Person
class, not instances. Then later you do:
person_array.push(Person.new(iq, speed, power, beauty))
And you end up with:
[Person, Person, Person, person_instance]
So when you iterate through and call send_for_beer
on that first item, it does have that method because send_for_beer
is an instance method that you are calling erroneously on a class object.
The fix here is to simply assign person_array
to an empty array literal, and then push things to it.
person_array = []
And a minor style note: <<
is usually preferred to Array#push
, making the filling of the array look more like this.
person_array << Person.new(iq, speed, power, beauty)
Ruby also support implicit return of the last expression in a method. So you do not need to return result
. Instead, simply calulate the return value as the only line in the method.
def send_for_beer
@iq * 2 + @speed * 10 + @power * 5 + @beauty
end
Instance variables don't quite work like that either. When you have @name
in the class body directly, you are not initializing instance variables for each instance. You are actually setting instance variable on the class object (which is weird, I know). What you actually need to do is set them from any instance method, typically initialize
, which you are doing here. So you can totally remove the instance variable setting at the class level here.
I think you've a syntax error in the method send_for_beer
, the =
sign is missing in the affectation of the variable result
.
By the way, the method can be written
def send_for_beer
@iq * 2 + @speed * 10 + @power * 5 + @beauty
end
If you have an array of fixed length, you can supply a block to create a new Person object for each element. You could rewrite your person_array line as follows:
person_array = Array.new(number_of_people) { Person.new(0, 0, 0, 0) }
Add the following line to the top of your class.
attr_writer(:iq, :speed, :power, :beauty)
This snipped of code could then modify the objects in your array.
person_array.each do |p|
p.iq, p.speed, p.power, p.beauty = rand(20) + 1, rand(5) + 1, 1
p.beauty = 10 if (rand(2) == 0)
end
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.