Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a private class method?

People also ask

How do I make my class method private?

The classic way to make class methods private is to open the eigenclass and use the private keyword on the instance methods of the eigenclass — which is what you commonly refer to as class methods.

What is private method in a class?

Private methods are those methods which can't be accessed in other class except the class in which they are declared. We can perform the functionality only within the class in which they are declared. But in C++ they can also access by Friend class. Public methods are those methods which can be accessed in any class.

Can class methods be private Ruby?

there's no such thing as "a private section" in Ruby. To define private instance methods, you call private on the instance's class to set the default visibility for subsequently defined methods to private... and hence it makes perfect sense to define private class methods by calling private on the class's class, ie.


private doesn't seem to work if you are defining a method on an explicit object (in your case self). You can use private_class_method to define class methods as private (or like you described).

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

Alternatively (in ruby 2.1+), since a method definition returns a symbol of the method name, you can also use this as follows:

class Person
  def self.get_name
    persons_name
  end

  private_class_method def self.persons_name
    "Sam"
  end
end

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

ExiRe wrote:

Such behavior of ruby is really frustrating. I mean if you move to private section self.method then it is NOT private. But if you move it to class << self then it suddenly works. It is just disgusting.

Confusing it probably is, frustrating it may well be, but disgusting it is definitely not.

It makes perfect sense once you understand Ruby's object model and the corresponding method lookup flow, especially when taking into consideration that private is NOT an access/visibility modifier, but actually a method call (with the class as its recipient) as discussed here... there's no such thing as "a private section" in Ruby.

To define private instance methods, you call private on the instance's class to set the default visibility for subsequently defined methods to private... and hence it makes perfect sense to define private class methods by calling private on the class's class, ie. its metaclass.

Other mainstream, self-proclaimed OO languages may give you a less confusing syntax, but you definitely trade that off against a confusing and less consistent (inconsistent?) object model without the power of Ruby's metaprogramming facilities.


By default all class methods are public. To make them private you can use Module#private_class_method like @tjwallace wrote or define them differently, as you did:

class << self

  private

  def method_name
    ...
  end
end

class << self opens up self's singleton class, so that methods can be redefined for the current self object. This is used to define class/module ("static") method. Only there, defining private methods really gives you private class methods.


Just for the completeness, we can also avoid declaring private_class_method in a separate line. I personally don't like this usage but good to know that it exists.

private_class_method  def self.method_name
 ....
end

I too, find Ruby (or at least my knowledge of it) short of the mark in this area. For instance the following does what I want but is clumsy,

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

My problems with the code above is that the Ruby syntax requirements and my code quality metrics conspire to made for cumbersome code. To have the code both work as I want and to quiet the metrics, I must make compare() a class method. Since I don't want it to be part of the class' public API, I need it to be private, yet 'private' by itself does not work. Instead I am force to use 'private_class_method' or some such work-around. This, in turn, forces the use of 'self.class.send(:compare...' for each variable I test in '==()'. Now that's a bit unwieldy.