When I said that every Ruby object has a class, I lied. The truth is, every object has two classes: a “regular” class and a singleton class. An object’s singleton class is a nameless class whose only instance is that object. Every object has its very own singleton class, created automatically along with the object. Singleton classes inherit from their object’s regular class and are initially empty, but you can open them up and add methods to them, which can then be called on the lone object belonging to them.
This is Ruby’s secret trick to avoid “class methods” and keep its type system simple and elegant
The above passage says that Ruby's secret trick to avoid class methods. I don't understand what the author means here. Where is Ruby stopping us to avoid class methods? for an example, look at the example shown below
class Raj
def self.hi
puts 'Hi'
end
def hello
puts 'hello'
end
end
object=Raj.new
object.hello
Raj.hi
As you can see in the preceding example, the class methods can still be created. yes? I understand that there are no true class methods in Ruby; instead, they are methods that are created for the Raj object. But, in any case, it's allowing me to create the method 'hi,' right? So, what does it mean when it says, 'This is Ruby's secret trick for avoiding "class methods" and keeping its type system simple and elegant'?
CodePudding user response:
I understand that there are no true class methods in Ruby; instead, they are methods that are created for the Raj object.
That's exactly it, though.
def self.hi
puts 'Hi'
end
This is not a class method or static method. Those don't exist in Ruby. That's the whole point. Your class Raj
defines an object of type Class
. We can see its type with the #class
function.
> Raj.class
=> Class
We can also see its ancestors.
> Raj.class.ancestors
=> [Class, Module, Object, PP::ObjectMixin, Kernel, BasicObject]
Class
inherits from Module
, since (for the most part) classes can do everything modules can. Module
, in turn, inherits from Object
, which has some modules of its own mixed in (PP:ObjectMixin
is for pretty-printing, and Kernel
gets you the nice helpers like puts
) and eventually inherits from the root class BasicObject
.
But this isn't the whole story, for Raj
has its own class as well: its singleton class. We can see the full story by calling #singleton_class
instead of #class
.
> Raj.singleton_class.ancestors
=>
[#<Class:Raj>,
#<Class:Object>,
#<Class:BasicObject>,
Class,
Module,
Object,
PP::ObjectMixin,
Kernel,
BasicObject]
Now there's a lot more going on. Raj
is an instance of the singleton class of Raj
, which inherits from the singleton class of Object
, which in turn inherits from the singleton class of BasicObject
, which inherits from Class
and all of the stuff we saw before.
So when you define a method on the class Raj
, you're defining it (as an instance method) on the singleton class #<Class:Raj>
. And that class (currently) has one instance: Raj
.
By the way, it's also useful to know that the term "singleton class" is a bit of a lie. As you can see, the class is very much not a singleton in general. For instance, the singleton class of Object
, called #<Class:Object>
above, actually has several instances: Object
, Raj
, String
, and most Ruby classes. Personally, I prefer to call them eigenclasses for that reason, but "singleton class" is the official (and more well-known) term.
CodePudding user response:
The author is talking about the singleton class in this sentence, there is a really nice article to deep dive into ruby singleton class: https://medium.com/@leo_hetsch/demystifying-singleton-classes-in-ruby-caf3fa4c9d91
Here is a nice example extracted from this article:
class Vehicle
def initialize(kms)
@kms = kms
end
def drive
puts "let's go!"
end
end
car = Vehicle.new(1000)
bus = Vehicle.new(3000)
def car.drive
print "I'm driving a car! "
super
end
car.drive # "I'm driving a car! let's go!"
bus.drive # "let's go!"
As you can see, here the #drive
method has been overridden but only for the car
object, the bus
object is still using the #drive
method defined in the Vehicle
class.
This new method is defined on the singleton class (or shadow class) of the object, this is allowing you to define new methods on the fly on an object without polluting all the objects of this class.
CodePudding user response:
This means that Ruby doesn't implement class methods.
Indeed, the Ruby OBJECT Model, allows you to "emulate" the definition of class methods by defining instance methods on the Eigenclass:
class Greeting
def self.hello
'hello world!'
end
def self.eigenclass
class << self
self
end
end
end
Greeting.eigenclass # => #<Class:Greeting>
Greeting.eigenclass.name # => nil
Greeting.singleton_methods # => [:hello, :eigenclass]
Greeting.eigenclass.instance_methods(false) # => [:hello, :eigenclass]
First, we define a Greeting.eigenclass
method. This method returns self
in the context of the eigenclass — by using the class << self ... end
syntax. In this case, self
contains an unnamed instance of the class Class
(a.k.a an anonymous class). This anonymous class keeps track of the class to which it is attached — the Greeting
class in our case.
Then, we can see that the singleton methods of the Greeting
class are the instance methods of the Greeting
eigenclass.
Feel free to have a look to this very detailed article to learn more about this concept.
CodePudding user response:
To illustrate @Sébastien P.'s answer:
dice = [1,2,3,4,5,6] #an ordinary array instance
def dice.throw #now it has an extra
sample
end
p dice.throw #=>3