2010-12-13 81 views
2

J'ai un peu de mal à comprendre quand "super" peut être appelé et quand ce n'est pas le cas. Dans l'exemple ci-dessous, la super méthode conduit à une erreur sans superclasse.Problème d'accès aux méthodes de superclasse dans les redéfinitions de méthode

class Bacterium 
    def eats 
    puts "Nam" 
    end 
end 

class Bacterium 
    def eats 
    super # -> no superclass error 
    puts "Yam" 
    end 
end 

b = Bacterium.new 
b.eats 

mais cela fonctionne:

class Fixnum 
    def times 
    super # -> works 
    puts "done" 
    end 
end 

5.times { |i| puts i.to_s } 

est de 5 pas seulement aussi une instance de Fixnum. Et je ne redéfinis pas une méthode existante comme dans l'exemple Bacterium ci-dessus?

Répondre

3

Non, pas vraiment. Fixnum hérite de la classe Integer et vous remplacez en fait Integer#times, de sorte que super fonctionne, car il appelle l'implémentation du parent.

Afin de réaliser quelque chose de similaire lorsque vous monkeypatching, vous devez alias méthode avant de le redéfinir, et il appelle par alias.

class Bacterium 
    alias_method :eats_original, :eats 
    def eats 
    eats_original # -> "Nam" 
    puts "Yam" 
    end 
end 

classe réouverture est pas une forme d'héritage et super est d'aucune utilité là.

+0

Merci, très bien expliqué! Absolument clair maintenant. – Zardoz

3

comme l'a dit Mladen, et vous pouvez vérifier que avec Class#superclass:

irb> Fixnum.superclass 
=> Integer 

Et ne Integer mettre en œuvre #times:

irb> Integer.instance_methods.grep /times/ 
=> [:times] 

Oui il le fait. Donc, d'une manière simplifiée, on peut dire que super appelle la méthode que vous êtes dans une superclasse. Dans votre cas, la superclasse d'un est Object, qui n'implémente pas #eats.

Je l'ai dit est très simplifiée, parce que regarder cet exemple:

module One 
    def hi 
    " World" << super() 
    end 
end 

module Two 
    def hi 
    "Hello" << super() 
    end 
end 

class SayHi 
    def hi 
    "!!!" 
    end 
end 

h = SayHi.new 
h.extend(One) 
h.extend(Two) 

puts h.hi 

#=> Hello World!! 

Ne prenez pas de sérieux ce que je l'ai écrit ici, il est en fait la pointe de l'iceberg du modèle d'objet Ruby, qui est important de comprendre (je l'apprends encore) - alors vous obtiendrez la plupart, ou tous ces concepts.

Utilisez Google-fu pour "modèle d'objet Ruby" ...

+0

Merci pour le bel exemple. Ruby est si puissant (mais aussi cause de toute sa puissance parfois un peu déroutant). – Zardoz

+0

Je veux juste ajouter ... si le module 'One' est inclus dans' SayHi' avant que la méthode 'hi' ne soit définie, alors' hi' de 'One' est disponible en tant que' super' dans 'SayHi'. L'ordre semble donc toujours important. – Zardoz

+1

@Zardoz: À mon humble avis, la meilleure chose à propos de Ruby n'est pas que c'est puissant (comme beaucoup d'autres langages modernes, vraiment), mais cela est réalisé sans ajouter de syntaxe spécifique et de mots-clés. 'alias_method' et' extend' sont (juste) des méthodes ordinaires, pas des constructions de langage ou quelque chose. –