2012-02-28 1 views
2

Je suis juste Startin apprendre Ruby et j'écrire un programme simple, mais j'ai une erreur undefined method 'send_for_beer' for Person:Class (NoMethodError) Voici un code:méthode non définie pour la classe ... (NoMethodError)

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 

Répondre

8

Voici votre problème:

person_array = Array.new(number_of_people, Person) 

En bref, ne font pas un tableau comme celui-ci. Utilisez la syntaxe littérale []. Ce que cela revient est:

[Person, Person, Person] 

qui est de 3 références à la classe Person, pas d'instances. Plus tard vous:

person_array.push(Person.new(iq, speed, power, beauty)) 

Et vous vous retrouvez avec:

[Person, Person, Person, person_instance] 

Ainsi, lorsque vous itérer et appelez send_for_beer sur ce premier élément, il ne dispose cette méthode parce send_for_beer est une méthode d'instance vous appelez par erreur sur un objet de classe.

La solution ici est d'attribuer simplement à un littéral de tableau vide, puis d'y ajouter des éléments.

person_array = [] 

Et une note de style mineur: << est généralement préféré Array#push, faisant regarder le remplissage du tableau plus comme celui-ci.

person_array << Person.new(iq, speed, power, beauty) 

Ruby supporte également le retour implicite de la dernière expression dans un procédé. Donc, vous n'avez pas besoin de return result. Au lieu de cela, il suffit de caluler la valeur de retour en tant que seule ligne de la méthode.

def send_for_beer 
    @iq * 2 + @speed * 10 + @power * 5 + @beauty 
end 

Les variables d'instance ne fonctionnent pas tout à fait comme ça non plus. Lorsque vous avez @name directement dans le corps de la classe, vous n'initialisez pas les variables d'instance pour chaque instance. Vous êtes en train de définir une variable d'instance sur l'objet de classe (ce qui est bizarre, je sais). Ce que vous avez réellement besoin de faire est de les définir à partir de n'importe quelle méthode d'instance, généralement initialize, ce que vous faites ici. Vous pouvez donc supprimer totalement le paramètre de variable d'instance au niveau de la classe ici.

1

Je pense que vous avez une erreur de syntaxe dans la méthode send_for_beer, le signe = est manquant dans l'affectation de la variable result.

Par ailleurs, la méthode peut être écrite

def send_for_beer 
    @iq * 2 + @speed * 10 + @power * 5 + @beauty 
end 
0

Si vous avez un tableau de longueur fixe, vous pouvez fournir un bloc pour créer un nouvel objet Personne pour chaque élément. Vous pouvez réécrire votre ligne person_array comme suit:

person_array = Array.new(number_of_people) { Person.new(0, 0, 0, 0) } 

Ajoutez la ligne suivante en haut de votre classe.

attr_writer(:iq, :speed, :power, :beauty) 

Cette coupure de code pourrait alors modifier les objets dans votre tableau.

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 
Questions connexes