47 votes

Méthodes en Ruby : objets ou pas ?

Inspiré par cette discussion Après quelques recherches sur Internet, je n'ai pas trouvé de réponse à une question assez simple concernant les méthodes en Ruby : les méthodes sont-elles des objets ou non ?

Il y a différentes opinions aquí y et j'aimerais vraiment entendre, disons, une explication approfondie.

Je suis au courant de Object#method qui prend un nom de méthode et renvoie une méthode Method mais, d'un autre côté, il y a une chose similaire que vous pouvez faire avec les blocs pour les transformer en Proc Les instances et les blocs ne sont pas des objets, alors en quoi les méthodes sont-elles différentes ?

0 votes

Les fonctions sont des citoyens de première classe en Ruby et peuvent être converties en objets, alors pourquoi s'inquiéter ? Je pense que la réponse sera de trop bas niveau pour avoir beaucoup de sens...

3 votes

Le sont-ils ? À mon avis, le fait que vous deviez les convertir en objets fait qu'ils ne sont pas de première classe. C'est aussi ce que je voudrais apprendre des réponses.

64voto

JRL Points 36674

Les méthodes sont un élément fondamental de la syntaxe de Ruby, mais ce ne sont pas des valeurs sur lesquelles les programmes Ruby peuvent opérer. C'est-à-dire que Les méthodes de Ruby ne sont pas objets de la manière dont les cordes, les nombres et les tableaux. Il est cependant possible, cependant, d'obtenir un objet Method qui représente une méthode donnée, et nous pouvons invoquer des méthodes indirectement par l'intermédiaire d'objets Method.

De Le langage de programmation Ruby :
alt text

0 votes

Bonjour, Si les méthodes ne sont pas des objets, comment est-ce possible ? irb(main):015:0> def hi irb(main):016:1> "hello" irb(main):017:1> end => nil irb(main):018:0> hi.object_id => 22452528 irb(main):019:0> hi.object_id.send hi => "hi" irb(main):020:0> hi.object_id.send(hi) => "hi"

11 votes

hi.object_id la méthode du premier appel hi et renvoie ensuite l'object_id de son résultat (qui est une chaîne de caractères). "hello" ).

21voto

Jörg W Mittag Points 153275

On ne peut pas vraiment dire.

La seule façon d'obtenir l'accès à une méthode est d'envoyer la commande #method à un objet, qui renverra ensuite un message Method objet. Mais est-ce que Method l'objet de la méthode elle-même ? Ou bien s'agit-il d'une enveloppe autour de la méthode ? Ou encore, s'agit-il d'une version convertie de la méthode originale ?

Vous ne pouvez pas savoir : si vous voulez consulter une méthode, vous devez appeler #method et à ce moment-là, vous avez définitivement sera obtenir un objet. Ce que c'était antes de vous avez appelé #method vous ne pouvez pas regarder, donc vous ne pouvez pas dire.

Quelques points de repère : en Ruby, tout renvoie une valeur. Ce que fait def retour ? C'est toujours renvoie à nil et non un Method objet. Et define_method ? Il renvoie un Proc mais pas un Method (ni un UnboundMethod ). [Note : dans Rubinius, def retourne le bytecode compilé de la méthode, mais toujours pas un Method objet.]

Si vous regardez les 4e et 5e paragraphes de la section 6.1 de la spécification du langage Ruby (lignes 29-34 et 1-5 des pages 5 et 6), vous pouvez clairement voir qu'une distinction est faite entre les méthodes et les objets. Et si vous regardez la spécification des classes intégrées, vous constaterez que ni l'une ni l'autre Method ni UnboundMethod sont là, ni Object#method . C'est-à-dire que vous pouvez construire un interpréteur Ruby parfaitement conforme aux normes dans lequel les méthodes ne sont pas objets.

Maintenant, les blocs OTOH définitivement ne sont pas objets. Il existe de nombreuses façons de construire Proc à partir de blocs, qui ont alors le même comportement que le bloc d'origine ( lambda , proc , Proc.new le & sigil), mais les blocs eux-mêmes ne sont pas des objets.

Pensez-y de cette façon : vous pouvez passer une chaîne de caractères à File.new pour construire un objet fichier, mais cela ne fait pas d'une chaîne un fichier. Vous pouvez passer un bloc à Proc.new pour construire un objet proc, mais cela ne fait pas d'un bloc un proc.

0 votes

Juste pour la référence : stackoverflow.com/questions/4294485/

2 votes

Je ne veux pas paraître sarcastique, mais qu'est-ce qu'un bloc ? S'agit-il simplement d'un morceau de texte dans un fichier .rb ?

0 votes

Jörg a précisé que les méthodes Ruby ne sont pas des objets dans une question StackOverflow ultérieure à laquelle @MladenJablanovic fait référence. Voici la citation : "Notez cependant que la méthode et la UnboundMethod sont des enveloppes autour de la méthode, et non la méthode elle-même. Les méthodes ne sont pas des objets en Ruby. (Contrairement à ce que j'ai écrit dans d'autres réponses, BTW. J'ai vraiment besoin de revenir en arrière et de les corriger).

11voto

yfeldblum Points 42613

En Ruby, les méthodes et les blocs ne sont pas, en soi, des objets natifs ou de première classe. Cependant, ils peuvent très facilement être enveloppés dans des objets, de sorte que cela ne fait généralement aucune différence.

Mais essayez, et gardez à l'esprit le résultat de,

a = Object.method(:new).object_id
b = Object.method(:new).object_id
a == b
=> false

En Haskell, toutes les valeurs (y compris les nombres ainsi que les lambdas et les fonctions) sont des valeurs de première classe. Dans tous les aspects du langage, elles sont toutes traitées de manière équivalente. Ce n'est pas le cas en Ruby, mais on peut s'en rapprocher.

0 votes

Justice, votre argument était le même que le mien. De plus, je ne connais pas d'autre moyen de renvoyer des méthodes, donc #method(method_name) semble être le seul moyen de référencer une méthode, à part l'appeler par son nom sur son objet d'origine.

1 votes

La seule chose que votre objet_id prouve est qu'ils ne sont pas immédiats. a = 1.0.object_id; b = 1.0.object_id; a == b # => false

2voto

bvrwoo_3376 Points 21

Les objets et les méthodes ne sont pas les mêmes, même si la valeur de retour des méthodes est un objet et non nul. Les objets vivent sur le tas, sauf s'ils sont dans une méthode, un lambda ou une portée de proc, et la méthode elle-même vit sur la pile et a une adresse assignée après interprétation, tandis que les objets statiques et de classe sont alloués sur le tas. Ruby utilise toujours le C pour l'interpréter et le passer à la structure VALUE.

2 votes

Du point de vue de Ruby, les méthodes sont des objets. Les détails d'implémentation ne sont pas importants. Une méthode peut être adressée et passée comme n'importe quel autre objet. Les Procs sont aussi des objets (et les blocs sont juste une manière syntaxique de créer un Proc/lambda).

1voto

Huliax Points 168

En Ruby, les méthodes ne sont pas des objets. Cela peut prêter à confusion car il existe une classe Method et vous pouvez obtenir des instances de Method. Ces instances ne sont que des mandataires de la méthode elle-même. Ces instances fournissent des fonctionnalités utiles. Elles disposent d'une magie interne qui les relie à la méthode elle-même (vous pouvez donc faire des choses comme Method#call ) mais vous ne pouvez pas réellement accéder à ces éléments (AFAIK).

1.method(:to_s).object_id == 1.method(:to_s).object_id #=> false

Cela signifie soit que 1 a deux #to_s (ce qui n'est pas le cas) ou que ce qui est renvoyé par la méthode #method n'est pas la méthode elle-même mais un proxy de la méthode. Si les méthodes étaient des objets, il y aurait des situations où l'on pourrait obtenir deux fois la même instance. Si les méthodes étaient des objets, vous seriez en mesure de faire des choses comme définir une variable d'instance sur elles et, plus tard, obtenir la valeur de cette variable d'instance après une deuxième récupération de l'objet de la méthode. Ce n'est pas possible. Donc, bien que cela puisse généralement ne font aucune différence, il y a des situations où je me trouve dans l'incapacité de faire les choses que je voudrais faire.

1.method(:to_s).instance_variable_set(:@foo, 'foo') #=> "foo" 
1.method(:to_s).instance_variable_get(:@foo)        #=> nil 
# And just in case you question it...
1.object_id == 1.object_id                          #=> true

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X