I'm near the finish of the Ruby track in Code Academy, and I'm curious about a peculiar thing: I was under the impression that a class is a repository of constants, methods, etc... and that in order to access most of them, you would first need to create an instance of that class or in some cases the methods of themselves can be invoked (as in they are all technically part of the global object). And then I saw something like this:
#Worked
Time.now
I understood as this as the method [now] of instance of class [Time] being invoked. I then tried to invoke the method on its own:
#Failed
now
and that failed, and I assumed that while a method can be created in the general scope [as part of the global object], if it relies on initialized variables of "parent" class, it cannot be called on its own, because it would not know which object to search for those initialized variables. Following that I created a test class:
class Clock
def initialize
@hours = 1
@minutes = 30
end
def showTime
puts "The time is: #{@hours}:#{@minutes}"
end
end
#this worked
watch = Clock.new
watch.showTime
#this failed
showTime
I then just created a basic method (assuming it's in the global level)
def mymethod
puts "The mighty METHOD!"
end
#Works
mymethod
and calling this method the way I did, without referencing the global object worked. So... the questions I have are as follows:
child class - The class that is doing the inheriting is called the child class. It inherits access to the object instance variables and methods in the parent class.
A derived class can be the base to further derived classes, creating an inheritance “tree” or hierarchy. A root class is the topmost class in an inheritance hierarchy.
Object class is the root or superclass of the class hierarchy, which is present in java.
First of all, your intuition is correct.
Every methods must be an instance method of some receiver.
Global methods are defined as private instance methods on Object
class and hence seem to be globally available. Why? From any context Object
is always in the class hierarchy of self
and hence private methods on Object
are always callable without receiver.
def fuuuuuuuuuuun
end
Object.private_methods.include?(:fuuuuuuuuuuun)
# => true
Class methods are defined as instance methods on the "singleton class" of their class instance. Every object in Ruby has two classes, a "singleton class" with instance methods just for that one single object and a "normal class" with method for all objects of that class. Classes are no different, they are objects of the Class
class and may have singleton methods.
class A
class << self # the singleton class
def example
end
end
end
A.singleton_class.instance_methods.include?(:example)
# => true
Alternative ways of defining class methods are
class A
def self.example
end
end
# or
def A.example
end
Fun fact, you can define singleton methods on any object (not just on class objects) using the same syntax def (receiver).(method name)
as follows
str = "hello"
def str.square_size
size * size
end
str.square_size
# => 25
"any other string".square_size
# => raises NoMethodError
Some programming language history — Singleton classes are taken from the Smalltalk language where they are called "metaclasses". Basically all object-oriented features in Ruby (as well as the functional-style enumerators on Enumerable
) are taken from the Smalltalk language. Smalltalk was an early class-based object-oriented language created in the 70ies. It was also the language that invented graphical user interfaces like overlapping windows and menus et cetera. If you love Ruby maybe also take a look at Smalltalk, you might fall in love yet again.
This is known as a class method. If CodeAcademy didn't cover it, that's a shame. Here's some examples:
# basic way
class Foo
def self.bar; :ok; end
end
Foo.bar # => :ok
# alternate syntax
class Foo
class << self
def bar; :ok; end
end
end
# alternate syntax, if Foo class already exists
def Foo.bar; :ok; end
# alternate approach if Foo class already exists
Foo.class_exec do
def bar; :ok; end
end
# to define a class method on an anonymous 'class' for a single instance
# you won't need to use this often
Foo.new.singleton_class.class_exec do
def bar; :ok; end
end
# to define a class method on an instance's actual class
Foo.new.class.class_exec do
def bar; :ok; end
end
Another way to get class methods is to extend
a module.
module FooMethods
def bar; :ok; end
end
module Foo
extend FooMethods
end
Foo.bar # => :ok
Note that with Modules, the methods are always defined as instance methods. This way they can be either extended
into class scope or included
into instance scope. Modules can also have class methods, using the exact same syntax / examples as shown above with classes. However there's not such as easy to load a module's class methods via include
or extend
.
How can [Time.now] be called in this fashion? Shouldn't there be an instance of Time first created?
The Time.now
method is a class method, not an instance method and therefore can be called directly on the Time
class rather than an instance of it Time.new
Class methods are defined on the class themselves using the self
keyword:
class Time
def self.now
# code
end
end
Time.now # works
Why can't I call the method [now] on its own? Am I right that it relies on resources that it cannot find when called this way?
When you call a method "on its own" you're actually implicitly calling it on self:
self.now
The above is the same as just doing:
now
Why could I not call the method showTime on its own? But if I define any method on the "global" level I can access it without referencing the global object
You defined the showTime
method on a specific class so you have to send that method to that class. When you define a method in the "global" scope you're implicitly defining it on self
and the subsequent call to mymethod
is actually self.mymethod
so it will work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With