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.