251 votes

création d'une méthode de classe privée

Comment se fait-il que cette approche de création d'une méthode de classe privée fonctionne:

 class Person

  def self.get_name
    persons_name
  end

  class << self
    private
      def persons_name
        "Sam"
      end
  end
end

puts "Hey, " + Person.get_name
puts "Hey, " + Person.persons_name  #=> raises "private method `persons_name' called for Person:Class (NoMethodError)"
 

mais cela ne veut pas

 class Person

  def self.get_name
    persons_name
  end

  private
    def self.persons_name
      "Sam"
    end
end

puts "Hey, " + Person.get_name
puts "Hey, " + Person.persons_name
 

306voto

tjwallace Points 2133

private ne semble pas fonctionner si vous définissez une méthode sur un objet explicite (dans votre cas, self ). Vous pouvez utiliser private_class_method pour définir les méthodes de classe comme étant privées (ou similaires à celles que vous avez décrites).

 class Person

  def self.get_name
    persons_name
  end

  def self.persons_name
    "Sam"
  end
  private_class_method :persons_name
end

puts "Hey, " + Person.get_name
puts "Hey, " + Person.persons_name
 

114voto

pvandenberk Points 1199

ExiRe a écrit:

Un tel comportement de ruby est vraiment frustrant. Je veux dire, si vous vous déplacez à la section privée de l'auto.méthode, puis il n'est PAS privé. Mais si vous vous déplacez à la classe << auto alors soudain, elle fonctionne. C'est tout simplement dégoûtant.

Confus il est probablement, frustrant, il peut bien être, mais dégueulasse ce n'est certainement pas.

Il a le sens parfait une fois que vous comprenez Ruby le modèle d'objet et de la méthode de recherche de flux, surtout quand on prend en considération le fait qu' private est PAS un accès/modificateur de visibilité, mais en fait un appel de méthode (avec la classe comme à son destinataire) comme discuté ici... il n'y a pas une telle chose comme "une section privée" en Ruby.

Pour définir privé instance méthodes, vous appelez private sur l'instance de la classe pour définir la valeur par défaut de la visibilité pour la suite des méthodes définies pour le privé... et donc il est parfaitement logique pour définir privé de la classe des méthodes en appelant private sur la classe la classe, c'est à dire. sa métaclasse.

Les autres grands, auto-proclamé OO langues peut vous donner une moins à confusion syntaxe, mais vous avez certainement du commerce que contre une source de confusion et de moins en moins cohérente (incompatible?) modèle d'objet, sans le pouvoir de Ruby métaprogrammation installations.

93voto

roxxypoxxy Points 195

Par défaut, toutes les méthodes de la classe sont publiques. Pour rendre privé, vous pouvez utiliser le Module#private_class_method comme @tjwallace écrit ou définir différemment comme vous l'avez fait

class << self

private
  def method_name
    ....
  end
end

la classe << auto ouvre l'auto de la classe singleton, de sorte que les méthodes peuvent être redéfinis pour le moi actuel de l'objet. Ce est utilisé pour définir la classe/module ("statique") de la méthode. La définition de méthode privée de plus, il ne vous donne privé de la méthode de classe.

6voto

dinman2022 Points 58

Moi aussi, trouver des Rubis (ou au moins à ma connaissance) à court de la marque dans ce domaine. Par exemple, la suivante est ce que je veux mais il est maladroit,

class Frob
    attr_reader :val1, :val2

    Tolerance = 2 * Float::EPSILON

    def initialize(val1, val2)
        @val2 = val1
        @val2 = val2
        ...
    end

    # Stuff that's likely to change and I don't want part
    # of a public API.  Furthermore, the method is operating
    # solely upon 'reference' and 'under_test' and will be flagged as having
    # low cohesion by quality metrics unless made a class method.
    def self.compare(reference, under_test)
        # special floating point comparison
        (reference - under_test).abs <= Tolerance
    end
    private_class_method :compare

    def ==(arg)
        self.class.send(:compare, val1, arg.val1) &&
        self.class.send(:compare, val2, arg.val2) &&
        ...
    end
end

Mes problèmes avec le code ci-dessus est que la syntaxe Ruby exigences et mon code métriques de qualité de conspirer à fait de la lourdeur du code. Pour avoir le code à la fois le travail que je veux et calme les valeurs, je dois faire comparer() une méthode de classe. Depuis que je ne veux pas qu'elle soit partie de la classe de l'API publique, j'ai besoin qu'il soit privé, mais "privé" par lui-même ne fonctionne pas. Au lieu de cela je suis de force à utiliser "private_class_method' ou de certaines de ces travaux. Ceci, à son tour, les forces de l'utilisation de auto.classe.envoyer(:comparer... " pour chaque variable je test dans '==()'. Maintenant que c'est un peu lourd.

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