1

A double colon(::) allows constants, instance methods, and class methods defined within a class or module, to be accessed from anywhere outside the class or module.

Looking at this example:

class Sample
   VAR_SAMPLE="what is the difference?"

  def self.show_var
    return VAR_SAMPLE
  end

  def method2
    return VAR_SAMPLE
  end
end

puts Sample::show_var # => what is the difference?
puts Sample.show_var # => what is the difference?
puts Sample::new::method2 # => what is the difference?
puts Sample.new.method2 # => what is the difference?

What is the difference in accessing class method using dot(.) and a double colon (::) operator then? Any thoughts are appreciated.

Fernand
  • 1,293
  • 1
  • 10
  • 18

2 Answers2

4

The double colon :: namespace operator can also be used as a message sending operator. In other words,

foo.bar

can also be written as

foo::bar

Except when not.

In particular, . is always a message send. :: is usually a namespace lookup, except when it cannot possibly be. That means, for example, you cannot call a message that starts with an uppercase character, unless you also pass an argument list.

foo = Class.new do
  def BAR; :method end
  BAR = :constant
end

foo.BAR    #=> :method
foo::BAR   #=> :constant
foo::BAR() #=> :method

The fact that :: can also be used for message sends is a historical curiosity, and is banned in most style guides except for "class factories", i.e. methods that return classes. Imagine a web framework that is set up like this:

module Controller
  def self.R(path)
    Class.new(AbstractController) do
      # a bunch of methods for dealing with routing to `path`
    end
  end
end

class IndexController < Controller::R '/index.html'
  def get
    render 'Welcome'
  end
end

In this case, in some style guides, it would be acceptable to write Controller::R because even though R is a method, it returns a class, so it kind-of acts like one.

But this is a special case for certain DSLs and is only allowed in certain style guides. Most style guides disallow :: for message sends, because it is redundant with ., because it already has a another different meaning (namespace resolution), and because it doesn't behave like . in all cases.

What is the difference in accessing class method using dot(.) and a double colon (::) operator then?

On the one hand, you can say, there is no difference because when used as the message sending operator, they both do the exact same thing.

On the other hand, there is a difference in syntax, namely that foo::BAR isn't a message send, it is a namespace lookup which is completely different. from foo.BAR, which is a message send.

Jörg W Mittag
  • 363,080
  • 75
  • 446
  • 653
0

You can call ruby methods using following ways

using Dot (.), Double Colon (::), send method & method method

class Sample
   VAR_SAMPLE="what is the difference?"

  def self.show_var
    return VAR_SAMPLE
  end
  
  def method2
    return VAR_SAMPLE
  end
end
puts Sample::show_var
puts Sample.show_var
puts Sample.send(:show_var)
puts Sample.method(:show_var).call
puts Sample::new::method2
puts Sample.new.method2
puts Sample.send(:new).send(:method2)
puts Sample.method(:new).call.method(:method2).call
# All the above will return `what is the difference?` only

Now consider method which is a private

class Sample
   VAR_SAMPLE="what is the difference?"

  private
  def self.show_var
    return VAR_SAMPLE
  end
end
puts Sample::show_var # Will throw error private method `show_var' called for
puts Sample.show_var # Will throw error private  method `show_var' called for
puts Sample.send(:show_var) # what is the difference?
puts Sample.method(:show_var).call # what is the difference?

Note:- Other than this you can call ruby methods using other metaprogramming methods as well.

Salil
  • 46,566
  • 21
  • 122
  • 156
  • Class methods don't respect `private`, you will be able to call `Sample.show_var` in your last example – Slam Oct 01 '20 at 14:59
  • omg, I didn't know private won't work in class methods T_T – Fernand Oct 02 '20 at 00:18
  • @slam but adding it to the eigenclass does e.g. `class Sample; VAR_SAMPLE="what is the difference?"; class << self; private; def show_var; VAR_SAMPLE; end;end;end` will cause `Sample.show_var` to raise "private method `show_var' called for Sample:Class" – engineersmnky Oct 02 '20 at 16:22
  • I guess, there's some reasons behind https://ruby-doc.org/core-2.7.1/Module.html#method-i-private_class_method – Slam Oct 02 '20 at 20:38