Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a difference between :: and . when calling class methods in Ruby?

Tags:

syntax

ruby

Simple question, but one that I've been curious about...is there a functional difference between the following two commands?

String::class String.class 

They both do what I expect -- that is to say they return Class -- but what is the difference between using the :: and the .?

I notice that on those classes that have constants defined, IRB's auto-completion will return the constants as available options when you press tab after :: but not after ., but I don't know what the reason for this is...

like image 854
Nathan Fritz Avatar asked Sep 04 '08 03:09

Nathan Fritz


People also ask

What does :: In Ruby mean?

The use of :: on the class name means that it is an absolute, top-level class; it will use the top-level class even if there is also a TwelveDaysSong class defined in whatever the current module is.

What happens when you call a method in Ruby?

In ruby, the concept of object orientation takes its roots from Smalltalk. Basically, when you call a method, you are sending that object a message. So, it makes sense that when you want to dynamically call a method on an object, the method you call is send . This method has existed in ruby since at least 1.8.


2 Answers

The . operator basically says "send this message to the object". In your example it is calling that particular member. The :: operator "drills down" to the scope defined to the left of the operator, and then calls the member defined on the right side of operator.

When you use :: you have to be referencing members that are defined. When using . you are simply sending a message to the object. Because that message could be anything, auto-completion does not work for . while it does for ::.

like image 92
Joseph Daigle Avatar answered Sep 20 '22 15:09

Joseph Daigle


Actually, auto-completion does work for .. The completion options are found by calling #methods on the object. You can see this for yourself by overriding Object.methods:

>> def Object.methods; ["foo", "bar"]; end => nil >> Object.[TAB] Object.foo  Object.bar >> Object. 

Note that this only works when the expression to the left of the . is a literal. Otherwise, getting the object to call #methods on would involve evaluating the left-hand side, which could have side-effects. You can see this for yourself as well:

[continuing from above...] >> def Object.baz; Object; end => nil >> Object.baz.[TAB] Display all 1022 possibilities? (y or n) 

We add a method #baz to Object which returns Object itself. Then we auto-complete to get the methods we can call on Object.baz. If IRB called Object.baz.methods, it would get the same thing as Object.methods. Instead, IRB has 1022 suggestions. I'm not sure where they come from, but it's clearly a generic list which isn't actually based on context.

The :: operator is (also) used for getting a module's constants, while . is not. That's why HTTP will show up in the completion for Net::, but not for Net.. Net.HTTP isn't correct, but Net::HTTP is.

like image 34
Peeja Avatar answered Sep 18 '22 15:09

Peeja