2012-06-09 2 views
55

Ce Ruby Style Guide indique qu'il vaut mieux utiliser self.method_name au lieu de class method_name. Mais pourquoi?class << self vs self.method avec Ruby: quoi de mieux?

class TestClass 
    # bad 
    class << self 
    def first_method 
     # body omitted 
    end 

    def second_method_etc 
     # body omitted 
    end 
    end 

    # good 
    def self.first_method 
    # body omitted 
    end 

    def self.second_method_etc 
    # body omitted 
    end 
end 

Existe-t-il des problèmes de performances?

+14

Il est difficile de prendre au sérieux une suggestion de style s'il n'y a pas d'explication, n'est-ce pas? –

+3

Notez qu'il est indiqué "_C'est un guide que nous utilisons pour nos propres applications Ruby en interne chez GitHub._" C'est-à-dire, c'est le style que Github a défini pour son propre usage. Ce n'est pas un guide définitif pour corriger le style Ruby. –

+1

Je suis d'accord, mais semble être écrit par des rubisistes bien formés avec des compétences d'autorité. –

Répondre

75

class << self est bon à garder toutes vos méthodes de classe dans le même bloc. Si des méthodes sont ajoutées dans def self.method à partir de ce moment-là, il n'y a aucune garantie (autre que la convention et les vœux pieux) qu'il n'y aura pas de méthode de classe supplémentaire cachée plus tard dans le fichier.

def self.method est bon à explicitement indiquant qu'une méthode est une méthode de classe, alors qu'avec class << self vous devez aller chercher le conteneur vous-même.

Lequel de ces est plus important pour vous est une décision subjective et dépend aussi des choses comme combien d'autres personnes travaillent sur le code et quelles sont leurs préférences.

+6

Je ne suis pas d'accord, ce n'est pas seulement un simple choix personnel. Il y a un inconvénient de lisibilité du code à l'utilisation de la réponse << << '- see @ Flexoid. L'inconvénient de la syntaxe 'self << de la classe et en utilisant un bloc de code, est que si le bloc est plus long que quelques méthodes, il n'est pas évident que ces méthodes sont des méthodes de classe, sauf si vous faites défiler jusqu'à la classe section self'. –

+1

Ce n'est pas un problème spécifique à 'class << self'. J'ai vu beaucoup de fichiers source (plus souvent dans de grands projets non triviaux) avec l'emboîtement profond du module, où il n'est pas clair jusqu'à ce que vous faites défiler vers le haut quelle * classe * une méthode est dans – Gareth

+0

@DmitriZagidulin Dans ce cas vous pouvez dire ces Les méthodes sont des méthodes de classe basées sur l'indentation. – weakish

5

Je suppose qu'ils pensent que self.* est mieux parce que vous pouvez dire avec certitude, c'est une méthode de classe ou d'instance, sans avoir à faire défiler et à explorer cette chaîne class << self.

+1

Je suis surpris par les autres réponses à cette question; C'est la seule façon de le faire. Si vous écrivez 'class << self', il est évident pour le lecteur que les méthodes sont des méthodes de classe si a) vous n'en avez qu'un petit nombre, * ET * b) la ligne' self << self' est actuellement visible dans votre éditeur. Il est également facile de grep pour les méthodes de classe et d'instance si vous suivez la convention 'def self.thing'. Dave Thomas suggère que «self» soit réservé lorsque vous avez besoin de changer «self» (dans le bloc, par exemple pour appeler attr_accessor sur la classe). –

+1

Mais à ce moment-là, serait-il aussi "illisible" d'avoir des méthodes privées? puisqu'ils sont tous indentés sous le mot-clé "privé". Je suppose que dans ruby, vous pouvez appeler explicitement "private: method" pour chaque méthode, mais étant donné le fonctionnement de la syntaxe C, je pense qu'il n'est pas déraisonnable de s'attendre à ce que les développeurs connaissent les contextes. –

28

En général, class << self est utilisé dans metaprogramming pour définir la classe comme soi-même pour une période de temps prolongée. Si je suis en train d'écrire 10 méthodes, je l'utiliser comme ceci:

METHOD_APPENDICES = [1...10] 
class << self 
    METHOD_APPENDICES.each do |n| 
    define_method("method#{n}") { n } 
    end 
end 

Cela créerait 10 méthodes (method1, method2, MÉTHODE3, etc.) qui vient retourner le nombre. Je voudrais utiliser class << self pour la clarté dans ce cas, car en métaprogrammation self est cruciale. Litière self. à l'intérieur il ferait effectivement les choses moins lisible.

Si vous êtes juste définir des méthodes de classe normalement, tenir à self.class_method_name parce que plus les gens sont susceptibles de le comprendre. Pas besoin d'introduire de méta-syntaxe à moins que vous n'attendiez que votre public le comprenne.

+0

Imho, la meilleure réponse. Cependant, cela donne une raison non-subjective à ce que ruby ​​ait 2 styles de syntaxe pour définir la méthode de classe. – 18augst

3

Celui que vous voulez. Les deux sont très clairs pour ce que vous faites. Mais je pense à certaines recommandations pour cela.

Quand il sont une seule méthode de classe pour définir, utilisation def self.xxx. Parce que pour définir une seule méthode, le niveau d'indentation croissant devient probablement encombrant.

Quand il sont plus d'une méthode de classe pour définir, utilisation class << self. Parce que l'écriture def self.xxx, def self.yyy et def self.zzz est certainement répétition. Créer une section pour ces méthodes.

Lorsque toutes les méthodes dans une classe sont méthode de classe, vous pouvez utilisermodule avec module_function au lieu de class. Cela vous permet de définir les fonctions du module, utilisez simplement def xxx.

+1

'étendre soi-même 'ne fonctionnera pas avec la classe. –

+0

Merci pour votre commentaire. J'ai corrigé ma réponse. – nonowarn

19

Comme indiqué ci-dessus, les deux styles semblent être équivalents, mais en utilisant class << self permet de marquer les méthodes de classe comme private ou protected.Par exemple:

class UsingDefSelf 
    def self.a; 'public class method'; end 
    private 
    def self.b; 'public class method!'; end 
end 

class UsingSingletonClass 
    class << self 
    def a; 'public class method'; end 
    private 
    def b; 'private class method'; end 
    end 
end 

private affecte uniquement les méthodes d'instance. En utilisant la classe singleton, nous définissons des méthodes d'instance de cette classe, qui se transforment en méthodes de classe de la classe contenant!

Nous pouvons également marquer les méthodes de classe comme private avec def self:

class UsingDefSelf 
    def self.a; 'private class method'; end 
    def self.b; 'private class method!'; end 
    private_class_method :a, :b 
    # In Ruby 2.1 there is an alternative syntax 
    private_class_method def self.c; 'private class method!'; end 
end 

Mais nous ne pouvons pas les marquer comme protected, il n'y a pas protected_class_method. (Cependant, puisque class est la seule instance de sa singletonclass, la méthode de classe privée et les méthodes de classe protégée sont presque identiques, sauf que leur syntaxe d'appel est différente.)

De même, il est moins facile que d'utiliser class << self pour marquer les méthodes de classe private, puisque vous devez lister tous les noms de méthode dans private_class_method ou préfixer private_class_method à chaque définition de méthode de classe privée.

-1

Jusqu'à présent, la question et les réponses ne discutent ces deux options:

class MyClass 
    def self.method_name 
    .. 
    end 
end 

class MyClass 
    class << self 
    def method_name 
     .. 
    end 
    end 
end 

Mais voici une autre option à envisager des méthodes/méthodes/méthodes statiques méthodes de classe/singleton qui opèrent au niveau de la classe (ou tout autre chose vous voulez les appeler):

class MyClass 
    def MyClass.method_name 
    .. 
    end 
end 

Je préfère cette option car elle est plus évidente. La définition de la méthode ressemble à la façon dont elle serait appelée dans votre code, et il est clair qu'elle fonctionne au niveau de la classe.

Je viens aussi d'un fond Python où self est utilisé pour les méthodes d'instance, alors que dans Ruby, self est utilisé pour les méthodes de classe. Cela me perturbe souvent, donc éviter de penser "est une méthode de soi dans Ruby une méthode de classe ou d'instance?" J'utilise def ClassName.methodname.

+0

"Je viens aussi d'un arrière-plan Python où self est utilisé pour les méthodes d'instance, alors que Ruby utilise self pour les méthodes de classe, ce qui me confond souvent" <- car "Ruby" est une "instance". Et dans la méthode d'instance Python est 'def m (self, args):', et Ruby est def(args) (omettre juste "self" et ":"). – weakish

+2

S'il vous plaît ne pas utiliser ce style, ruby ​​est une langue avec une communauté très opiniâtre. Cela permet aux développeurs de coder côte à côte sans trop expliquer ou sur les choses. Cela définit simplement vos propres normes uniques. –

+0

@AditSaxena ayant un guide de style pour votre projet/équipe résout cela. (FWIW, je n'utilise plus l'option que j'ai proposée car je programme presque exclusivement en Ruby maintenant et je me suis habitué à 'self', mais il est toujours bon de connaître les différentes options.) – Dennis

Questions connexes