Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can some classes and/or methods be called without instances of their parent class?

Tags:

class

ruby

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:

  1. How can [Time.now] be called in this fashion? Shouldn't there be an instance of Time first created?
  2. 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?
  3. 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
like image 402
brooklynsweb Avatar asked Jan 19 '17 21:01

brooklynsweb


People also ask

Do child class inherit instance variables?

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.

Which is the top most class of all the classes?

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.

What is the base class of all classes in Java?

Object class is the root or superclass of the class hierarchy, which is present in java.


Video Answer


3 Answers

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.

like image 193
akuhn Avatar answered Oct 16 '22 12:10

akuhn


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.

like image 31
max pleaner Avatar answered Oct 16 '22 12:10

max pleaner


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.

like image 35
DiegoSalazar Avatar answered Oct 16 '22 11:10

DiegoSalazar