Sunday, June 26, 2016

Ruby Classes

Introduction to classes in Ruby

Classes are at the heart of object-oriented programming (OOP). A class is a way of grouping related variables and functions into a single container. This container is called an "object". Put another way, a class is like a blueprint from which objects are created.

Let's use a car blueprint as an example and define a simple class:


class Car
attr_accessor :color
end

In the above example:
  • class is a keyword used to create classes;
  • Car is the name of the class;
  • attr_accessor is an attribute accessor, which is a method that allows us to read and write instance variables from outside the class (this will be explained later);
  • :color is an attribute, which is a component of a class (such as a variable) which can be accessed from the outside;
  • end ends the class declaration

Instances (objects)


Generally, in order to use a class, we need to create an instance. Continuing the car example, a class is a blueprint and an instance is an actual car. In other words, an instance is an object built from the blueprint provided by a class. The words instance and object are used interchangeably.

The syntax for instantiating a class is:


instance_name = ClassName.new 

Let's try it with the class created above:


# Create an instance of the Car class 
civic = Car.new     
 
# Set a value for the color attribute 
civic.color = "silver" 
 
# Read the value of the color attribute 
civic.color        # Output: => "silver" 

We could create any number of instances of the Car class and store them in a collection such as an array or a hash. Each instance could have a different value for the "color" attribute.

We named the object civic but we could have used any other name. Convention dictates that class names should be written in CamelCase and object names in snake_case.

Reflection: examining objects


Reflection, also known as introspection, is the ability to programmatically examine (inspect) classes, objects, methods, etc. In other words, the application provides information about its own code and state. That is useful in the context of metaprogramming, debugging and understanding code written by other people.

Inspecting objects

The inspect method returns a human-readable string representation of any object, including the class name, a hexadecimal representation of the object ID, and the names and values of the object's variables (instance variables).


class Meditation 
  def initialize 
    @name = "zazen" 
    @minutes = 40 
  end  
end 
 
m = Meditation.new 
 
m.inspect  # Output: => "#<Meditation:0x00000001c87e08 @name=\"zazen\", @minutes=40>" 

When writing a class, we can override the inspect method to provide more useful information about its objects.

Testing if an object is an instance of a specific class

There are several ways to check whether an object is an instance of a particular class.


class Meditation 
end 
 
zazen = Meditation.new 
 
Meditation === zazen  # Output: => true 
zazen.is_a? Meditation  # Output: => true 
zazen.instance_of? Meditation # Output: => true 

Both === and is_a? methods return true if the object is an instance of the given class or any of its ancestors. The instance_of? method is stricter and only returns true if the object is an instance of that specific class, not an ancestor. The term "ancestor" is related to class inheritance and will be explained soon.

There is also the kind_of method, which is just a different name for is_a?.


Kernel.instance_method(:kind_of?) == Kernel.instance_method(:is_a?) # Output: => true 

In the following example, we create one more instance, then get a list of all instances of the of the Meditation class.


kinhin = Meditation.new 

ObjectSpace.each_object(Meditation) { |x| puts x } 
Output:

#<Meditation:0x00000001dd85a0> 
#<Meditation:0x00000001de1ba0> 

The above output is a string representation of the two instances of the Meditation class (zazen and kinhin). We could use the above code, for instance, to read or write an attribute in all instances of a class.

Classes are also objects


Almost everything is an object in Ruby, even classes. All classes are instances of a built-in class called Class.


class Foo 
end 
 
# The newly created Foo class is an instance of the built-in Class class. 
Foo.instance_of? Class    # Output: => true 
 
# Instances of the Foo class are, well, just instances of the Foo class…  
f = Foo.new 
f.instance_of? Foo    # Output: => true 
f.instance_of? Class    # Output: => false 

That may be easier to grasp when represented visually.


Class (built-in class) 
   | 
   |--- Foo (instance of Class) 
         | 
         |--- f (instance of Foo) 

When starting to learn OOP, it's easy to confuse instantiation with inheritance (which will be discussed later). However, they are completely different things. In the above example, the Foo class is an instance of the built-in Class named class. Foo is not a subclass of Class; there is no inheritance relationship between them.

Ruby's built-in classes are also instances of the Class class.


String.instance_of? Class    # Output: => true 
Integer.instance_of? Class    # Output: => true 

The initialize method


Every time an object is created (a class is instantiated), Ruby looks for a special method called initialize within the class. If it's there, it's automatically executed. Defining the initialize method is optional; if it's not defined, nothing happens.

The initialize method is often used to set default values to instance variables. In the example below, all new instances of the Car class are created with "black" as the default value for the color instance variable.


class Car 
  attr_accessor :color 
 
  def initialize 
    @color = "black" 
  end 
end 
 
c = Car.new 
c.color    # Output: => "black" 

We can also add parameters when defining the initialize method. When instantiating a class, any arguments passed to the new method are received by the initialize method.


class Car 
  attr_accessor :color 
 
  def initialize(color) 
    @color = color 
  end 
end 
 
c = Car.new  # Output: ArgumentError: wrong number of arguments (given 0, expected 1) 
 
# The "silver" argument passed here will be received by the initialize method 
c = Car.new "silver"   
c.color  # Output: => "silver" 

initialize handles arguments like any other method. It can have positional parameters (required and optional), a single splat parameter, keyword parameters (required and optional) and a double splat parameter. It may also receive a block implicitly or have an explicit block parameter (prefixed with &). This post about methods explains how each type of parameter/argument works.

Note that Ruby implicitly makes initialize a private method and silently discards its return value.

Attributes and accessor methods


Attributes are class components that can be accessed from outside the object. They are known as properties in many other programming languages. Their values are accessible by using the "dot notation", as in object_name.attribute_name. Unlike Python and a few other languages, Ruby does not allow instance variables to be accessed directly from outside the object.


class Car 
  def initialize 
    @wheels = 4  # This is an instance variable 
  end 
end 
 
c = Car.new 
c.wheels     # Output: NoMethodError: undefined method `wheels' for #<Car:0x00000000d43500> 

In the above example, c is an instance (object) of the Car class. We tried unsuccessfully to read the value of the wheels instance variable from outside the object. What happened is that Ruby attempted to call a method named wheels within the c object, but no such method was defined. In short, object_name.attribute_name tries to call a method named attribute_name within the object. To access the value of the wheels variable from the outside, we need to implement an instance method by that name, which will return the value of that variable when called. That's called an accessor method. In the general programming context, the usual way to access an instance variable from outside the object is to implement accessor methods, also known as getter and setter methods. A getter allows the value of a variable defined within a class to be read from the outside and a setter allows it to be written from the outside.

In the following example, we have added getter and setter methods to the Car class to access the wheels variable from outside the object. This is not the "Ruby way" of defining getters and setters; it serves only to illustrate what getter and setter methods do.


class Car 
  def wheels  # getter method 
    @wheels 
  end 
 
  def wheels=(val)  # setter method 
    @wheels = val 
  end 
end 
 
f = Car.new 
f.wheels = 4  # The setter method was invoked 
f.wheels  # The getter method was invoked 
# Output: => 4 

The above example works and similar code is commonly used to create getter and setter methods in other languages. However, Ruby provides a simpler way to do this: three built-in methods called attr_reader, attr_writer and attr_acessor. The attr_reader method makes an instance variable readable from the outside, attr_writer makes it writeable, and attr_acessor makes it readable and writeable.

The above example can be rewritten like this.


class Car 
  attr_accessor :wheels 
end 
 
f = Car.new 
f.wheels = 4 
f.wheels  # Output: => 4 

In the above example, the wheels attribute will be readable and writable from outside the object. If instead of attr_accessor, we used attr_reader, it would be read-only. If we used attr_writer, it would be write-only. Those three methods are not getters and setters in themselves but, when called, they create getter and setter methods for us. They are methods that dynamically (programmatically) generate other methods; that's called metaprogramming.

The first (longer) example, which does not employ Ruby's built-in methods, should only be used when additional code is required in the getter and setter methods. For instance, a setter method may need to validate data or do some calculation before assigning a value to an instance variable.

It is possible to access (read and write) instance variables from outside the object, by using the instance_variable_get and instance_variable_set built-in methods. However, this is rarely justifiable and usually a bad idea, as bypassing encapsulation tends to wreak all sorts of havoc.

Inheritance


Trough inheritance, a class acquires (inherits) components from another class.

A class that inherits from another class is called subclass, also known as child class or derived class. The class that is inherited (where the inherited components are implemented) is called superclass or parent class. We will use these terms interchangeably throughout this post. You will also see the terms ancestor and descendant. Ancestors are all classes above a specific class in its inheritance hierarchy; descendants are all classes below it.

Usually, the superclass (parent) is more general and its subclasses (children) add further specialization. For instance, a class called Car may specify that cars have 4 wheels, a steering wheel and so on. This class may inherit from a class called Vehicle that implements the details of combustion engines and will also be inherited by the Motorcycle class. Another example is a Polygon class which contains common characteristics of all polygons and is inherited by other classes named Square and Triangle.

Some programming languages such as C++, Perl, and Python allow one class to inherit from multiple other classes; that is called multiple inheritance. Ruby does not support multiple inheritance. That means each class can only inherit from one other class. However, many classes can inherit from the same class.

Again, beware not to confuse inheritance with instantiating, as they are completely different things.

Method overriding


Method overriding allows a subclass to provide its own implementation of an inherited method. When there are two methods with the same name, one in the superclass and another on the subclass, the implementation of the subclass will override the one from the superclass. That happens only within the subclass, the original method implementation within the superclass is not affected.


class A 
  def meditate 
    puts "Practicing zazen…" 
  end 
end 
 
class B < A 
  def meditate 
    puts "Practicing kinhin…" 
  end 
end 
 
b = B.new 
b.meditate     # Output: Practicing kinhin… 

The super keyword


As seen above, if both superclass and subclass have methods of the same name, the implementation of the subclass will prevail (inside the subclass). However, instead of overriding the implementation of the superclass, we might need to add extra functionality. Using the super keyword within the subclass allows us to do that; super calls the superclass implementation of the corresponding method. In other words, it allows the overriding method to call the overridden method.


class Zazen 
  def meditate 
    puts "Practicing Zazen…" 
  end 
end 
 
class Sitting < Zazen 
  def meditate 
    puts "Sitting…" 
    super # Calls the meditate method implemented in the parent class 
    puts "Getting up…" 
  end 
end 
 
s = Sitting.new 
s.meditate 
Output:

Sitting… 
Practicing Zazen… 
Getting up… 

Notice how, in the example above, the statements from both meditate methods (implemented in both classes) were executed.

How super handles arguments

Regarding argument handling, the super keyword can behave in three ways:

When called with no arguments, super automatically passes any arguments received by the method from which it's called (at the subclass) to the corresponding method in the superclass.


class A 
  def some_method(*args) 
    puts "Received arguments: #{args}" 
  end 
end 
 
class B < A 
  def some_method(*args) 
    super 
  end 
end 
 
b = B.new 
b.some_method("foo", "bar")     # Output: Received arguments: ["foo", "bar"] 

If called with empty parentheses (empty argument list), no arguments are passed to the corresponding method in the superclass, regardless of whether the method from which super was called (on the subclass) has received any arguments.


class A 
  def some_method(*args) 
    puts "Received arguments: #{args}" 
  end 
end 
 
class B < A 
  def some_method(*args) 
    super()  # Notice the empty parentheses here 
  end 
end 
 
b = B.new 
b.some_method("foo", "bar")     # Output: Received arguments: [ ] 

When called with an explicit argument list, it sends those arguments to the corresponding method in the superclass, regardless of whether the method from which super was called (on the subclass) has received any arguments.


class A 
  def some_method(*args) 
    puts "Received arguments: #{args}" 
  end 
end 
 
class B < A 
  def some_method(*args) 
    super("baz", "qux")  # Notice that specific arguments were passed here 
  end 
end 
 
b = B.new 
b.some_method("foo", "bar")     # Output: Received arguments: ["baz", "qux"] 

Reflection: examining the inheritance hierarchy of a class


Ruby provides reflective methods which return information about a class's inheritance chain.


class AsianReligion 
end 
 
class Buddhism < AsianReligion 
end 
 
class Zen < Buddhism 
end 

Let's suppose we need to identify the relationship between the above classes (regarding inheritance), while being unable to look at the above code.

Check if the Zen class is a descendant of the Buddism and AsianReligion classes:


Zen < Buddhism  # Output: => true 
Zen < AsianReligion  # Output: => true 

Identify the superclass of the Zen class:


Zen.superclass  # Output: => Buddhism 

Get a list of all ancestors of the Zen class. The ancestors method returns the whole inheritance hierarchy (Zen and all classes above it) and all the modules included in these classes. In the following example, we exclude any modules, leaving only ancestor classes.


Zen.ancestors - Zen.included_modules  # Output => [Zen, Buddhism, AsianReligion, Object, BasicObject] 

Notice how the three classes defined above are included, along with a couple of Ruby's built-in classes called Object and BasicObject. All classes inherit implicitly from these two built-in classes. However, explaining the Ruby Core Object Model is outside the scope of this post.

Rails provides the descendants and subclasses methods to list a class descendants and direct subclasses. Ruby does not provide a built-in method to do that. We can, however, use the following code; it returns the names of all descendants of the AsianReligion class (and the class itself).


ObjectSpace.each_object(AsianReligion.singleton_class).to_a 
# Output: => [Buddhism, AsianReligion, Zen] 

Polymorphism


Briefly put, polymorphism is to call the same method in different objects and get different results. We are actually calling different implementations of the method (entirely different methods with the same name). Hence, the different results.

There are three types of polymorphism: inheritance polymorphism, interface polymorphism, and abstract polymorphism. This post covers the first two but not the third, as it is usually implemented by using abstract classes, which are not supported by Ruby.

Inheritance Polymorphism


In Ruby, polymorphism is usually implemented through inheritance, as in the example below. Remember that if both child and parent classes define methods with the same name, the implementation of the subclass prevails, and the one from the superclass is overridden.


class Mammal 
  @@vertebrate = true 
  @@endothermic = true 
  @@fur = true 
 
  def make_sound 
    raise NotImplementedError, "The make_sound method should be implemented in the subclass." 
  end 
end 
 
class Cat < Mammal
end 
 
class Dog < Mammal
  def make_sound 
    puts "Woof" 
  end 
end 
 
c = Cat.new  
c.make_sound  # Output: NotImplementedError: The make_sound method should be implemented in the subclass. 
 
d = Dog.new 
d.make_sound  # Output: Woof 

In the example above, notice how both Cat and Dog classes are subclasses of Animal. To understand polymorphism, just look at the make_sound method implemented at the Animal class; it does nothing except making sure that all subclasses of Animal implement their own make_sound method.

Interface Polymorphism


Different methods with the same name are implemented in distinct classes and do different things. An example is the + method. Remember that, in Ruby, lots of operators such as + are implemented as methods. That means 2 + 3 is syntactic sugar (a convenient shortcut) for 2.+(3).

Different classes provide distinct implementations of the + method. When called on a string object, it will concatenate two operands:


"foo" + "bar"  # Output: => "foobar" 

When called on a float, it will sum two operands:


1.0 + 1.0  # Output: => 2.0 

When called on an array, it will merge two operands into a single new array.


[ "foo", "bar" ] + [ "baz" ]  # Output => ["foo", "bar", "baz"] 

Each one of the three classes (String, Float, and Array) provides its own implementation of the + method. That means, the appropriate method (implementation) is always called, depending on the context. That is an example of interface polymorphism.

Duck Typing


Duck typed objects are defined by what they do, instead of their type. In other words, instead of requiring an object to be an instance of a particular class, we require it to respond to one or more specific methods. The term duck typing comes from the saying "if the object walks like a duck and quacks like a duck, then it must be a duck".

The + method can also be used as an example of duck typing. In the following example, we created a method called sum, which takes two arguments; regardless of the types of the objects passed as arguments, it expects them to respond to the + method.


def sum(a, b) 
  a + b 
end 
 
# Integers, strings and arrays respond to the + method as expected 
sum(1,1)  # Output:  => 2 
sum("foo", "bar")  # Output: => "foobar" 
sum([1,2,3], [4,5])  # Output: => [1, 2, 3, 4, 5] 
 
# Hashes and ranges do not respond to the + method 
sum({a:1}, {b:2})  # Output: NoMethodError: undefined method `+' for {:a=>1}:Hash 
sum(0..1, 2..3)  # Output: NoMethodError: undefined method `+' for 0..1:Range 

Usually, we only check whether the object implements a method by a specific name. However, the method may exist but return something unexpected. That can be avoided by thoroughly testing our code, and most good developers will do just that.

Variable types


Ruby provides five types of variables: global, instance, class, local and constant. This post covers the last four plus class instance variables, which are a particular type of instance variable. Global variables are not covered because, in the vast majority of cases, using them is a bad practice.

Instance variables


Instance variables are defined within instance methods, and their names begin with @. Their value is only accessible within the specific object on which it was set. In other words, when we modify the value of an instance variable, the change only applies to that particular instance. Unlike local variables which are only available within the method where they were defined, instance variables are accessible by all methods within the object (instance methods of the class). Instance variables are the most commonly used type of variable in Ruby classes.


class Car 
  attr_reader :color 
 
  def set_color(color_receiverd_as_argument) 
    @color = color_receiverd_as_argument 
  end 
end 
 
car1 = Car.new  
car1.color     # Output: => nil   
car1.set_color "black" 
car1.color     # Output: => "black" 
 
car2 = Car.new 
car2.set_color "silver" 
car2.color    # Output: => "silver" 

In the example above, notice that:
  • Trying to access an instance variable before it's initialized will not raise an exception. Its default value is nil.
  • Changing the value of the color variable in one instance of the Car class does not affect the value of the same variable in the other instances.
To get a list of all instance variables of a class, use the instance_variables method, which returns an array of instance variable names.


class Car 
  def initialize 
    @wheels = 4 
  end 
end 
 
c = Car.new 
c.instance_variables  # Output: => [:@wheels]  

Note that only initialized instance variables (those who were already given a value) are shown by the instance_variables method.

As seen earlier in this post, instance variables need accessor methods to be read and written from outside the object.

Class variables


Class variables are defined at the class level, outside any methods. Their names begin with @@, and their values can be read or written from within the class itself or any of its subclasses and instances. Class variables can be accessed by both class methods and instance methods (explained further below).


class Car 
  @@count = 0        # This is a class variable 
 
  def initialize 
    @@count += 1    # Increment the count each time the class is instantiated 
    puts @@count 
  end 
 
  # This is a getter method, used to read the @@count class variable from outside 
  def count 
    @@count 
  end 
end 
 
# Create 3 instances of the Car class 
car1 = Car.new 
car2 = Car.new 
car3 = Car.new 
 
car1.count    # Output: => 3 
car2.count    # Output: => 3 
car3.count    # Output: => 3 

In the example above, the @@count class variable is initialized (given a value) at the class level. Then, each time the Car class is instantiated, the initialize method is executed, and the value of @@count is incremented by 1. The count method is a getter, required to access the @@count class variable from outside the class. Note that accessor methods (explained above) such as attr_access, attr_read, and attr_write do not work with class variables. Rails provides accessor methods that work with class variables, named cattr_accessor, cattr_reader and cattr_writer.

Notice how @@count is accessible inside the initialize and count instance methods. Also, its value persists between all instances of the Car class.

Any changes in a class variable value will reflect on all of its instances and subclasses. Whether the value is changed in the class where the variable was defined or any of its descendants, it changes throughout the whole hierarchy.

Let's continue the example above:


class Sedan < Car 
  def mess_up_count 
    @@count = 345 
  end 
end 
 
s = Sedan.new 
s.count        # Output: => 4 
 
s.mess_up_count 
s.count        # Output: => 345 
car3.count    # Output: => 345 

In the example above, the Sedan subclass class inherited @@count and its value from Car. Then, we called the mess_up_count method, which changed the value of @@count to 345. Notice how the value of @@count in the car3 object (instance of the Car class) was also changed. This often causes undesired effects, and it's the reason why class variables are not often used in Ruby.

The class_variables method returns an array containing the names of all class variables in a specific class. It includes inherited class variables, as well as those defined within the class. If used with the false flag, like Car.class_variables(false), it omits inherited class variables.


Car.class_variables  # Output: => [:@@count] 

It is possible to access (read and write) class variables from outside the class, by using the class_variable_get and class_variable_set built-in methods. That's included in this post for the sake of completeness, but it's usually a terrible practice as it breaks encapsulation.

Class instance variables


Class instance variable names also begin with @. However, they are defined at class level, outside any methods. Class instance variables can only be accessed by class methods. They are shared amongst all instances of a class but not its subclasses. In other words, they are not inheritable. If the value of a class instance variable is changed in one instance of the class, all other instances are affected. Earlier we saw how all classes are instances of a built-in class called Class. That is what makes class instance variables possible.


class Vehicle 
  @count = 0        # This is a class instance variable 
 
  def initialize 
    self.class.increment_count 
    self.class.show_count 
  end 
 
  def self.increment_count    # This is a class method 
    @count += 1 
  end 
 
  def self.show_count        # This is a class method 
    puts @count 
  end 
 
end 
 
class Car < Vehicle 
  @count = 0 
end 
 
v1 = Vehicle.new    # Output: 1 
v2 = Vehicle.new    # Output: 2 
v3 = Vehicle.new    # Output: 3 
 
car1 = Car.new        # Output: 1 
car2 = Car.new        # Output: 2 
 
v3 = Vehicle.new    # Output: 4 

Let's review the example above. A class instance variable called @count is set in the Vehicle class, with an initial value of 0. Every time the Vehicle class is instantiated, the initialize method calls self.increment_count to increment the value of @count and self.show_count to return the new value. Then, we have the Car class, which is a subclass of Vehicle and inherits all of its methods. However, it does not inherit the @count class instance variable, as this type of variable is not inheritable. That's why the counter works within the Car class, but it has its own count.

Methods prefixed with self., such as self.increment_count and self.show_count, are class methods. That is the only kind of method capable of accessing class instance variables. We will get back to class methods soon.

Local variables


A local variable within a class is like any other local variable in Ruby. It is only accessible within the exact scope on which it's created. If defined within a method, it is only available inside that method.


class Car  
  def initialize 
    wheels = 4 
  end 
   
  def print_wheels 
    print wheels 
  end 
end 
 
c = Car.new 
c.print_wheels        # Output: NameError: undefined local variable or method `wheels'…     

Constants


Constants are used to store values that should not be changed. Their names must start with an uppercase letter. By convention, most constant names are written in all uppercase letters with an underscore as word separator, such as SOME_CONSTANT.

Constants defined within classes can be accessed by all methods of that class. Those created outside a class can be accessed globally (within any method or class).


class Car  
  WHEELS = 4 
 
  def initialize 
    puts WHEELS 
  end 
end 
 
c = Car.new     # Output: 4 

Note that Ruby does not stop us from changing the value of a constant, it only issues a warning.


SOME_CONSTANT = "foo" 
SOME_CONSTANT = "bar" 
warning: already initialized constant SOME_CONSTANT 
warning: previous definition of SOME_CONSTANT was here 

In Ruby, all class and module names are constants, but convention dictates they should be written in camel case, such as SomeClass.

Constants can be accessed from outside the class, even within another class, by using the :: (double colon) operator. To access the WHEELS constant from outside the Car class, we would use Car::WHEELS. The :: operator allows constants, public instance methods and class methods to be accessed from outside the class or module on which they are defined.

A built-in method called private_constant makes constants private (accessible only within the class on which they were created). The syntax is as follows:


class Car  
  WHEELS = 4 
 
  private_constant:WHEELS 
end 
 
Car::WHEELS    # Output: NameError: private constant Car::WHEELS referenced 

Class methods and instance methods


Instance methods


All methods defined inside a class with the def method_name syntax are instance methods. They are the most common type of method seen in Ruby code.


class Koan 
  def say_koan 
    puts "What is your original face before you were born?" 
  end 
end 
 
k = Koan.new 
k.say_koan    # Output: What is your original face before you were born? 

The built-in method instance_methods returns an array containing the names of all instance methods of a class. The false flag excludes inherited instance methods.


Koan.instance_methods(false)  # Output: => [:say_koan] 

Class methods


Class methods can be called directly on the class, without instantiating it. Their names are prefixed with self. As seen above, only class methods can access class instance variables.


class Zabuton 
  def self.stuff 
    puts "Stuffing zabuton…" 
  end 
end 
 
# Call the class method without instantiating the class 
Zabuton.stuff  # Output: Stuffing zabuton… 
Zabuton::stuff  # Output: Stuffing zabuton… 
 
# Call the class method through an object 
z = Zabuton.new 
z.class.stuff  # Output: Stuffing zabuton… 

The following syntax can also be used to define class methods and will produce the same result as the above syntax. Remember this example; we will get back to it later to explain the meaning of class << self.


class Zabuton 
  class << self 
    def stuff 
      puts "Stuffing zabuton…" 
    end 
  end 
end 

We can also call a class method from within an instance method, by prefixing it with self.class, as in the following example.


class Zabuton 
  def initialize 
    self.class.stuff  # calling the stuff class method 
  end 
 
  def self.stuff 
    puts "Stuffing zabuton…" 
  end 
end 
 
z = Zabuton.new    # Output: Stuffing zabuton… 

The built-in method called methods returns an array including the names of all class methods of a specific class. If used with the false flag, inherited class methods are omitted.


Zabuton.methods(false)  # Output: => [:stuff] 

Public, Private, and Protected methods


Ruby provides three types of methods: public, private, and protected.

Public Methods


Public methods are most widely used and can be accessed from outside the class.


class Koan 
  def say_koan 
    puts "How do you catch a flying bird without touching it?" 
  end 
end 
 
k = Koan.new 
k.say_koan    # Output: How do you catch a flying bird without touching it? 

In the above example, we were able to call the say_koan method from outside the object because it is a public method. No further explanation is required as all examples in this post (up to this point) are public methods.

To list all public instance methods in a class, use the public_instance_methods built-in method. To list public class methods, use public_methods. As usual, the false flag excludes inherited methods.


Koan.public_instance_methods(false)  # Output: => [:say_koan] 

Private Methods


To define a private method, we use the private keyword, which is actually a built-in method implemented in a class called Module. A private method can only be called by another method within the class on which it was defined (or one of its subclasses).


class Koan 
  def call_say_koan 
    say_koan 
  end 
 
  private 
    def say_koan 
      puts "What is the sound of one hand clapping?" 
    end 
end 
 
k = Koan.new 
k.say_koan    # Output: NoMethodError: private method `say_koan' called for #<Koan:0x000000021e7380> 
k.call_say_koan        # Output: What is the sound of one hand clapping? 

In the above example, we could not call the say_koan private method directly (from outside the class), but we could call the call_say_koan public method which, in turn, called say_koan.

Also in the above example, the built-in private method was used with no arguments. Hence, all methods defined below it were made private.

The private method can also be used with previously defined method names (passed as symbols) as arguments.


class Foo 
  def some_method 
  end 
 
  private :some_method 
end 

In order to make a class method private, use the private_class_method keyword/method instead of private.

Private methods can't be called with a receiver, such as self. Trying to call the say_koan method with self as a receiver (self.say_koan) within call_say_koan would result in the following exception:


NoMethodError: private method `say_koan' called for #<Koan:0x000000021eb548> 

As of Ruby 2.0, the respond_to? method will return false when given a private method as an argument.


k.respond_to? :say_koan  # Output: => false

To list all private instance methods in a class, use the private_instance_methods built-in method. For private class methods, use private_methods.


Koan.private_instance_methods(false)  # Output => [:say_koan] 

Protected Methods


To define a protected method, we use the protected keyword (which is actually a method). Like private methods, protected methods can also be called by other methods within the class on which it was defined (or one of its subclasses). The difference is, protected methods can also be called from within other instances of the same class.

There is no such thing as a protected a class method, Ruby only supports protected instance methods.

Let's suppose we need to select a few meditators to participate in a study. To find the most experienced meditators, we need to compare their total hours of meditation. However, we don't want the number of hours to be visible.


class Meditator 
  def initialize(hours) 
    @hours = hours 
  end 
   
  def more_experienced?(other_person) 
    hours > other_person.hours 
  end 
   
  protected 
    attr_reader :hours  # We have made the accessor protected 
end 
   
m1 = Meditator.new 3000 
m2 = Meditator.new 5000 
 
m2.more_experienced? m1  # Output: => true 
m1.more_experienced? m2  # Output: => false 

Similar code could be used to protect any kind of sensitive data from outside access (outside the class and its instances), although protected methods are not commonly employed in Ruby.

When called with no arguments (as in the above example), the protected method turns all methods defined below it into protected methods. It can also be used to protect previously defined methods, as in the following example.


class Foo 
  def some_method 
  end 
 
  protected :some_method 
end 

To list all protected instance methods in a class, use the protected_instance_methods built-in method. For protected class methods, use protected_methods.


Meditator.protected_instance_methods(false)  # Output: => [:hours] 

The self keyword


The self keyword is always available, and it points to the current object. In Ruby, all method calls consist of a message sent to a receiver. In other words, all methods are invoked on an object. The object on which the method is called is the receiver, and the method is the message. If we call "foo".upcase, the "foo" object is the receiver and upcase is the message. If we don't specify an object (a receiver) when calling a method, it is implicitly called on the self object.

Self keyword at class level


When used within a class but outside any instance methods, self refers to the class itself.


class Foo 
  @@self_at_class_level = self   
 
  def initialize 
    puts "self at class level is #{@@self_at_class_level}" 
  end 
end 
 
f = Foo.new     # Output: self at class level is Foo 

Self keyword at instance methods


When inside an instance method, the self keyword refers to that specific instance. In other words, it refers to the object where it was called.


class Meditation 
  def initialize 
    puts "self within an instance method is #{self}" 
  end 
end 
 
zazen = Meditation.new     # Output: self within an instance method is #<Meditation:0x00000000ab2b38> 

Notice that #<Meditation:0x00000000ab2b38> is a string representation of the zazen object, which is an instance of the Meditation class.

For the next example, we will use a module. Modules will be covered further below but, in the current context, the Meditable module is used as a container for storing methods which will be added to and used by the Sitting class.


module Meditable 
  def meditate 
    "Practicing #{self.meditation_name}…"   
  end 
end 
 
class Sitting 
  include Meditable 
  attr_accessor:meditation_name 
 
  def initialize(meditation_name) 
    @meditation_name = meditation_name 
  end 
end 
 
s = Sitting.new "zazen" 
s.meditate    # Output:  => "Practicing zazen…" 

In the above example, the self keyword refers to the instance of the Sitting class from which the meditate method was called.

Singleton Methods and Metaclasses


All instance methods defined in this post's examples are global methods. That means they are available in all instances of the class on which they were defined. In contrast, a singleton method is implemented on a single object.

There is an apparent contradiction. Ruby stores methods in classes and all methods must be associated with a class. The object on which a singleton method is defined is not a class (it is an instance of a class). If only classes can store methods, how can an object store a singleton method? When a singleton method is created, Ruby automatically creates an anonymous class to store that method. These anonymous classes are called metaclasses, also known as singleton classes or eigenclasses. The singleton method is associated with the metaclass which, in turn, is associated with the object on which the singleton method was defined.

If multiple singleton methods are defined within a single object, they are all stored in the same metaclass.


class Zen 
end 
 
z1 = Zen.new 
z2 = Zen.new 
 
def z1.say_hello  # Notice that the method name is prefixed with the object name 
  puts "Hello!" 
end 
 
z1.say_hello    # Output: Hello! 
z2.say_hello    # Output: NoMethodError: undefined method `say_hello'… 

In the above example, the say_hello method was defined within the z1 instance of the Zen class but not the z2 instance.

The following example shows a different way to define a singleton method, with the same result.


class Zen 
end 
 
z1 = Zen.new 
z2 = Zen.new 
 
class << z1 
  def say_hello 
    puts "Hello!" 
  end 
end 
 
z1.say_hello    # Output: Hello! 
z2.say_hello    # Output: NoMethodError: undefined method `say_hello'… 

In the above example, class << z1 changes the current self to point to the metaclass of the z1 object; then, it defines the say_hello method within the metaclass.

Both of the above examples serve to illustrate how singleton methods work. There is, however, an easier way to define a singleton method: using a built-in method called define_singleton_method.


class Zen 
end 
 
z1 = Zen.new 
z2 = Zen.new 
 
z1.define_singleton_method(:say_hello) { puts "Hello!" } 
 
z1.say_hello    # Output: Hello! 
z2.say_hello    # Output: NoMethodError: undefined method `say_hello'… 

We learned earlier that classes are also objects (instances of the built-in class called Class). We also learned about class methods. Well, class methods are nothing more than singleton methods associated with a class object. The following example was already seen in the section about class methods. After learning about metaclasses, we may look at it again with a deeper understanding.


class Zabuton 
  class << self  
    def stuff 
      puts "Stuffing zabuton…" 
    end 
  end 
end 

All objects may have metaclasses. That means classes can also have metaclasses. In the above example, class << self modifies self so it points to the metaclass of the Zabuton class. When a method is defined without an explicit receiver (the class/object on which the method will be defined), it is implicitly defined within the current scope, that is, the current value of self. Hence, the stuff method is defined within the metaclass of the Zabuton class. The above example is just another way to define a class method. IMHO, it's better to use the def self.my_new_clas_method syntax to define class methods, as it makes the code easier to understand. The above example was included so we understand what's happening when we come across the class << self syntax.

Ruby provides other useful built-in methods for handling singleton methods and metaclasses.

singleton_class: Returns the singleton class of an object. If there is no singleton class, one is created.


Zen.singleton_class    # Output: => #<Class:Zen> 

singleton_method: Looks for a singleton method and returns a corresponding method object, which can be stored in a variable, passed around, and called with the call method.


s = z1.singleton_method(:say_hello) 
s.call    # Output: => Hello! 

singleton_methods: Returns an array of names of the singleton methods associated with a specific object.


z1.singleton_methods  # Output: => [:say_hello]  

Modules as mixins


Modules are used as namespaces and as mixins. This post only covers (briefly) mixins. Using modules for namespacing is well explained in this post at the Practicing Ruby website.

We learned before that Ruby does not support multiple inheritance. However, there are cases where a class would benefit by acquiring methods defined within multiple other classes. That is made possible by using a construct called module. A module is somewhat similar to a class, except it does not support inheritance, nor instantiating. It is mostly used as a container for storing multiple methods. One way to use a module is to employ an include or extend statement within a class. That way, the class gains access to all methods and objects defined within the module. It is said that the module is mixed in the class. So, a mixin is just a module included in a class. A single module can be mixed in multiple classes, and a single class can mix in multiple modules; thus, any limitations imposed by Ruby's single inheritance model are eliminated by the mixin feature.

All modules are instances of the Module class.


module Foo 
end 
 
Foo.instance_of? Module  # Output: => true 

In the following example, the JapaneseGreetings module is included (as a mixin) in the Person class.


module JapaneseGreetings 
  def  hello 
    puts "Konnichiwa" 
  end 
 
  def goodbye 
    puts "Sayōnara" 
  end 
end 
 
class Person 
  include JapaneseGreetings  
end 
 
p = Person.new 
p.hello  # Output: Konnichiwa 
p.goodbye  # Output: Sayōnara 

Modules deserve a post of their own; this is only a brief introduction.

Classes are modules


Remember how all classes are instances of a built-in class called Class? Well, Class is a subclass of Module (another built-in class).


Class.superclass  # Output: => Module 

Most of the built-in methods used to manipulate classes are defined in the Module class. Notice how the following list includes many of the methods discussed in this post.


Module.instance_methods(false) 
 => [:<=>, :module_exec, :class_exec, :<=, :>=, :==, :===, :include?, :included_modules, :ancestors, :name, 
 :public_instance_methods, :instance_methods, :private_instance_methods, :protected_instance_methods, :const_get,
 :constants, :const_defined?, :const_set, :class_variables, :class_variable_get, :remove_class_variable, 
 :class_variable_defined?, :class_variable_set, :private_constant, :public_constant, :singleton_class?, 
 :deprecate_constant, :freeze, :inspect, :module_eval, :const_missing, :prepend, :method_defined?, :class_eval,
 :public_method_defined?, :private_method_defined?, :<, :public_class_method, :>, :protected_method_defined?,
 :private_class_method, :to_s, :autoload, :autoload?, :instance_method, :public_instance_method, :include] 

As we already learned, it is standard practice to implement "generic" code (which can be used in different contexts) in the superclass and add extra specialization within subclasses. An example is how the Class class inherits all the above instance methods from the Module class and implements three additional methods.


Class.instance_methods(false) 
 => [:new, :allocate, :superclass] 

The allocate method allocates memory and creates a new "empty" instance of the class, without calling the initialize method. The new method calls allocate, then invokes the initialize method on the newly created object. As for superclass, it returns the name of the superclass of a given class.

In his book The Ruby Programming Language, Yukihiro Matsumoto (the creator of Ruby, AKA Matz) demonstrates how the new method would look like if it were written in Ruby:


def new(*args) 
  o = self.allocate # Create a new object of this class 
  o.initialize(*args) # Call the object's initialize method with our args 
  o # Return new object; ignore return value of initialize 
end 

In brief, we might say that classes are modules with two significant extra functionalities: inheritance and instantiation. Another difference is that, unlike modules, classes cannot be used as mixins.

Thank you for reading. If this post was useful, consider subscribing to our mailing list (click "Subscribe" at the top right of the page) to be notified when new posts are published.

332 comments:

  1. I don't like mixing religion and programming. I think it trivialises both of them. Interesting article, but would be better split into multiple parts. Overall, good.

    ReplyDelete
    Replies
    1. Thank you for your feedback. I respect your opinion about mixing religion and programming. This blog does not intend to trivialize any of those subjects. Also, I'm Buddhist, so I have the utmost respect for Zen.

      About the length of the post, it is not meant to be a quick reference; it is targeted at people who prefer to study each subject thoroughly. The same type of people who would read a 600-page book on Ruby. However, I understand that this may not be the case for most people, so you have a valid point.

      Delete
    2. great article and good response to a somewhat critical comment

      Delete
  2. I agree with the ioquatix in that there is a lot of information here. I suggest you break out this topic into smaller bite-sized articles that is easier to digest.

    ReplyDelete
    Replies
    1. I have just answered ioquatix's comment about the length of the post. Regardless, the next posts will probably be shorter. Thanks for your feedback.

      Delete
  3. Great article for newbies, thank you :)

    ReplyDelete
  4. Nice article, especially the bit about meta classes; many attempts are made to shed light on them but they often leave the reader more confused than when they started. Not the case here. 8)

    ReplyDelete
    Replies
    1. I'm glad to hear that. Thank you for your feedback.

      Delete
  5. Replies
    1. Great Article. Thank you for sharing! Really an awesome post for every one.

      IEEE Final Year projects Project Centers in Chennai are consistently sought after. Final Year Students Projects take a shot at them to improve their aptitudes, while specialists like the enjoyment in interfering with innovation. For experts, it's an alternate ball game through and through. Smaller than expected IEEE Final Year project centers ground for all fragments of CSE & IT engineers hoping to assemble. Final Year Project Domains for IT It gives you tips and rules that is progressively critical to consider while choosing any final year project point.

      JavaScript Training in Chennai

      JavaScript Training in Chennai

      Delete
  6. It's interesting that many of the bloggers to helped clarify a few things for me as well as giving.Most of ideas can be nice content.The people to give them a good shake to get your point and across the command.

    software testing course in chennai

    ReplyDelete
  7. Well Said, you have furnished the right information that will be useful to anyone at all time. Thanks for sharing your Ideas.
    Web Design Training

    ReplyDelete
  8. Thank you so much for sharing this worth able content with us. The concept taken here will be useful for my future programs and I will surely implement them in my study.
    nebosh course in chennai

    ReplyDelete
  9. I am reading your post from the beginning, it was so interesting to read & I feel thanks to you for posting such a good blog, keep updates regularly.
    industrial safety course in chennai

    ReplyDelete
  10. Thanks for sharing such informative blog!!! It gives precise information about the software performance in real time.
    Linux training in hyderabad

    ReplyDelete
  11. Nice post. Thanks for sharing! I want people to know just how good this information is in your article. It’s interesting content and Great work.
    Thanks & Regards,
    VRIT Professionals,
    No.1 Leading Web Designing Training Institute In Chennai.

    And also those who are looking for
    Web Designing Training Institute in Chennai
    SEO Training Institute in Chennai
    Photoshop Training Institute in Chennai
    PHP & Mysql Training Institute in Chennai
    Android Training Institute in Chennai

    ReplyDelete
  12. Permainan BandarQ Online adalah salah satu permainan yang paling populer yang dimainkan karena memiliki putaran yang sangat cepat dibandingkan permainan lainnya
    asikqq
    dewaqq
    sumoqq
    interqq
    pionpoker
    bandar ceme terbaik
    hobiqq
    paito warna terlengkap
    syair sgp

    ReplyDelete
  13. Thanks for splitting your comprehension with us. It’s really useful to me & I hope it helps the people who in need of this vital information.
    Sql server dba online training

    ReplyDelete
  14. I feel this article have given such a lot of vital info for me. And I am satisfied studying your article. However wanna commentary on few general things, The website style is ideal, the articles are truly nice.
    Interior Designers in Chennai | Interior Decorators in Chennai | Best Interior Designers in Chennai | Home Interior designers in Chennai | Modular Kitchen in Chennai

    ReplyDelete
  15. Download and install Vidmate App which is the best HD video downloader software available for Android. Get free latest HD movies, songs, and your favorite TV shows.

    ReplyDelete
  16. Download latest audio and video file fromvidmate

    ReplyDelete
  17. Download latest audio and video file fromvidmate

    ReplyDelete
  18. It is amazing and wonderful to visit your site.Thanks for sharing this information,this is useful to me...Your good knowledge and kindness in playing with all the pieces were very useful. I don’t know what I would have done if I had not encountered such a step like this.
    Selenium online training
    Selenium certification training
    Selenium online course
    Selenium training course

    ReplyDelete
  19. Thank you for sharing such great information with us. I really appreciate everything that you’ve done here and am glad to know that you really care about the world that we live in.
    Data Science Online Training
    Data Science Online Certification
    Data Science Online Course
    Data Science Training Course

    ReplyDelete
  20. Thanks for Sharing This Article.It is very so much valuable content. I hope these Commenting lists will help to my website
    microservices online training

    ReplyDelete
  21. A IEEE project is an interrelated arrangement of exercises, having a positive beginning and end point and bringing about an interesting result in Engineering Colleges for a particular asset assignment working under a triple limitation - time, cost and execution. Final Year Project Domains for CSE In Engineering Colleges, final year IEEE Project Management requires the utilization of abilities and information to arrange, plan, plan, direct, control, screen, and assess a final year project for cse. The utilization of Project Management to accomplish authoritative objectives has expanded quickly and many engineering colleges have reacted with final year IEEE projects Project Centers in Chennai for CSE to help students in learning these remarkable abilities.



    Spring Framework has already made serious inroads as an integrated technology stack for building user-facing applications. Spring Framework Corporate TRaining the authors explore the idea of using Java in Big Data platforms.
    Specifically, Spring Framework provides various tasks are geared around preparing data for further analysis and visualization. Spring Training in Chennai


    ReplyDelete
  22. Thanks for Sharing This Article.It is very so much valuable content. I hope these Commenting lists will help to my website
    best angular js online training

    ReplyDelete
  23. Really i found this article more informative, thanks for sharing this article! Also Check here

    Download and install Vidmate App which is the best HD video downloader software available for Android. Get free latest HD movies, songs, and your favorite TV shows

    Vidmate App Download

    Vidmate apk for Android devices

    Vidmate App

    download Vidmate for Windows PC

    download Vidmate for Windows PC Free

    Vidmate Download for Windows 10

    Download Vidmate for iOS

    Download Vidmate for Blackberry

    Vidmate For IOS and Blackberry OS

    ReplyDelete
  24. BSc in Optometry – Here is the details about Best BSc Optometry Colleges In Bangalore. If you are looking to study in Bangalore, the below link will redirect to a page that will show the best OPT colleges in Bangalore
    Optometry Colleges In Bangalore

    ReplyDelete



  25. I am really happy to say it’s an interesting post to read . I learn new information from your article , you are doing a great job . Keep it up and a i also want to share some information regarding selenium training course and selenium videos

    ReplyDelete
  26. Idnplay
    IDN Poker88 | Situs Poker Deposit Pulsa | Agen Poker Terpercaya
    Agen Resmi Poker Idnplay Terpercaya dan resmi Lesensi ayok join sekarang juga untuk mendapatkan promo2 terbaik dari situs agen poker online sekarang juga !!

    ReplyDelete
  27. This comment has been removed by the author.

    ReplyDelete
  28. GrueBleen – One of the best branding and marketing agency in Riyadh- Saudi Arabia. If you need the details, click the below link
    Branding Agency Riyadh
    Marketing Agency Riyadh

    ReplyDelete
  29. BSc Cardiac Care Technology – Here is the details about Best BSc Cardiac Care Technology Colleges In Bangalore. If you are looking to study in Bangalore, the below link will redirect to a page that will show the best BCC colleges in Bangalore
    BSc Cardiac Care Technology Colleges In Bangalore
    BSc in Optometry – Here is the details about Best BSc Optometry Colleges In Bangalore. If you are looking to study in Bangalore, the below link will redirect to a page that will show the best OPT colleges in Bangalore. If you are looking to study BSc Optometry in Bangalore, click the below link.
    Optometry Colleges In Bangalore

    ReplyDelete
  30. I have to search sites with relevant information on given topic and provide them to teacher our opinion and the article.
    data analytics courses
    data science interview questions

    ReplyDelete
  31. Jadi, PayPal ini merupakan salah satu sistem ataupun mekanisme pembayaran yang nantinya bisa dilakukan dengan secara on the web. Nah, kunjungi pulsa dengan paypal pada intinya PayPal tersebut adalah sebuah perusahaan yang memang menawarkan jasa transfer ataupun penerimaan uang melalui surat elektronik.

    ReplyDelete
  32. Digital Marketing due to exponential growth in internet users have created lots of opportunities by targeting users searching for something.
    ExcelR Digital Marketing Courses In Bangalore

    ReplyDelete
  33. The very next time I read a blog, I hope that it doesn't fail me just as much as this one. I mean, Yes, it was my choice to read, however I actually believed you would have something interesting to say. All I hear is a bunch of complaining about something that you could possibly fix if you were not too busy seeking attention.
    Click here to getMoreinformation.

    ReplyDelete
  34. I am inspired with your post writing style & how continuously you describe this topic. After reading your post, thanks for taking the time to discuss this software testing courses online , I feel happy about it and I love learning more about this topic.

    ReplyDelete
  35. Kingdomtoto situs judi togel yang setiap hari memberikan kemenangan dengan mudah. Kingdomtoto juga cocok sebagai bandar darat alternatif untuk bermain togel online. Untuk melihat hasil result pasaran togel juga bisa disini ya bos.
    Situs yang sama kami refferensikan untuk anda yaitu kinghorsetoto. Situs paito warna terlengkap.

    ReplyDelete
  36. This is a wonderful article, Given so much info in it, These type of articles keeps the users interest in the website, and keep on sharing more ... good luck... Thank you!!! digital marketing courses in Bangalore

    ReplyDelete
  37. There are lots of information about latest technology and how to get trained in them, like sql server tutorial for beginners and microsoft sql server tutorial have spread around the web, but this is a unique one according to me.

    ReplyDelete
  38. Poker online situs terbaik yang kini dapat dimainkan seperti Bandar Poker yang menyediakan beberapa situs lainnya seperti http://62.171.128.49/hondaqq/ , kemudian http://62.171.128.49/gesitqq/, http://62.171.128.49/gelangqq/, dan http://62.171.128.49/seniqq. yang paling akhir yaitu http://62.171.128.49/pokerwalet/. Jangan lupa mendaftar di panenqq

    ReplyDelete
  39. Thanks for the interesting blog that you have implemented here. Very helpful and innovative. Waiting for your next upcoming article.
    Digital Marketing Course In Kolkata

    ReplyDelete
  40. Anda juga dapat bertaruh pada pasangan nomor yang menang. Anda dapat memilih pasangan depan (dua pertama), pasangan belakang (dua terakhir) atau pasangan terbagi (nomor pertama dan ketiga) dari kemungkinan kombinasi dan kemudian dengan sedikit keyakinan 98toto

    ReplyDelete
  41. Such a very useful article. Very interesting to read this article.I would like to thank you for the efforts you had made for writing this awesome article. bangalore digital marketing course

    ReplyDelete

  42. This post is really nice and informative. The explanation given is really comprehensive and informative. I also want to say about the online marketing training

    ReplyDelete
  43. Awesome article, it was exceptionally helpful! I simply began in this and I'm becoming more acquainted with it better. The post is written in very a good manner and it contains many useful information for me. Thank you very much and will look for more postings from you.


    digital marketing blog
    digital marketing bloggers
    digital marketing blogs
    digital marketing blogs in india
    digital marketing blog 2020
    digital marketing blog sites
    skartec's digital marketing blog
    skartec's blog
    digital marketing course
    digital marketing course in chennai
    digital marketing training
    skartec digital marketing academy

    ReplyDelete
  44. I have to search sites with relevant information on given topic ExcelR Digital Marketing Course Pune and provide them to teacher our opinion and the article.

    ReplyDelete
  45. keep up the good work. this is an Ossam post. This is to helpful, i have read here all post. i am impressed. thank you. this is our machine learning courses in Mumbai
    machine learning courses in Mumbai | https://www.excelr.com/machine-learning-course-training-in-mumbai

    ReplyDelete
  46. Thanks for this blog are more informative contents step by step. I here by attached my site would you see this blog.

    7 tips to start a career in digital marketing

    “Digital marketing is the marketing of product or service using digital technologies, mainly on the Internet, but also including mobile phones, display advertising, and any other digital medium”. This is the definition that you would get when you search for the term “Digital marketing” in google. Let’s give out a simpler explanation by saying, “the form of marketing, using the internet and technologies like phones, computer etc”.

    we have offered to the advanced syllabus course digital marketing for available join now.

    more details click the link now.

    https://www.webdschool.com/digital-marketing-course-in-chennai.html

    ReplyDelete
  47. Amazing article useful information.

    Web designing trends in 2020

    When we look into the trends, everything which is ruling today’s world was once a start up and slowly begun getting into. But Now they have literally transformed our lives on a tremendous note. To name a few, Facebook, Whats App, Twitter can be a promising proof for such a transformation and have a true impact on the digital world.

    we have offered top the advanced syllabus course web design and development for available join now.

    more details click the link now.

    https://www.webdschool.com/web-development-course-in-chennai.html

    ReplyDelete
  48. This Was An Amazing ! I Haven't Seen This Type of Blog Ever ! Thankyou For Sharing, data science course in Hyderabad

    ReplyDelete
  49. Great web site you have got here.. It’s hard to find quality writing like yours these days. get I truly appreciate individuals like you! Take care!!

    ReplyDelete
  50. Way cool! Some very valid points! I appreciate you penning this post plus the rest of the site is really Web develop good.

    ReplyDelete
  51. Inspirational Blog The Content Mentioned is Knowledgeable and Very Effective .Thanks For Sharing It

    Artificial Intelligence Course Training In Hyderabad

    ReplyDelete
  52. I become greater than happy to uncover this notable internet site on line. I need to to thank you to your time due to this brilliant examine latest!! I genuinely loved each bit of it and I have you ever bookmarked to look new information to your blog.

    ReplyDelete
  53. It is amazing and wonderful to visit your site.Thanks for sharing this information,this is useful to me...
    http://chennaitraining.in/bi-bw-training-in-chennai/
    http://chennaitraining.in/solidworks-training-in-chennai/
    http://chennaitraining.in/autocad-training-in-chennai/
    http://chennaitraining.in/ansys-training-in-chennai/
    http://chennaitraining.in/revit-architecture-training-in-chennai/
    http://chennaitraining.in/primavera-training-in-chennai/

    ReplyDelete
  54. Great blog !It is best institute.Top Training institute In chennai
    http://chennaitraining.in/oracle-dba-training-in-chennai/
    http://chennaitraining.in/sql-server-dba-training-in-chennai/
    http://chennaitraining.in/teradata-training-in-chennai/
    http://chennaitraining.in/sap-hr-training-in-chennai/
    http://chennaitraining.in/sap-fico-training-in-chennai/
    http://chennaitraining.in/sap-abap-training-in-chennai/

    ReplyDelete
  55. I have been reading for the past two days about your blogs and topics, still on fetching! Wondering about your words on each line was massively effective.... Candidates can check their result easily within few seconds through this page when the officials release Sarkari result. On our webpage, we are providing all the State Government/ Central Government/ PSC/ Entrance Exam Results

    ReplyDelete
  56. Welcome to the party of my life here you will learn everything about me.
    Pune Digital Marketing Course

    ReplyDelete

  57. TeaTv Apk Is Another One Of The Best Online Streaming Application For Smartphone Users. This Application Is Available For Android & IOS Users. Also, You Can Connect This Application Easily With Amazon Firestick, Android Smart TVs, Start Settop Box, Etc. There are more apk to online streaming is Mediabox apk for smartphone users ( Android and ios ) and
    Best Wishes Quotes 
    Watch Free online Movies 
    onhax 
    onhax android 
    Hulu Apk 

    ReplyDelete
  58. Awesome blog, I enjoyed reading your articles. This is truly a great read for me. I have bookmarked it and I am looking forward to reading new articles. Keep up the
    good work!.data analytics courses

    ReplyDelete

  59. TeaTv Apk Is Another One Of The Best Online Streaming Application For Smartphone Users. This Application Is Available For Android & IOS Users. Also, You Can Connect This Application Easily With Amazon Firestick, Android Smart TVs, Start Settop Box, Etc. There are more apk to online streaming is Mediabox apk for smartphone users ( Android and ios ) and
    Best Wishes Quotes 
    Watch Free online Movies 
    onhax 
    onhax android 
    Hulu Apk 

    ReplyDelete
  60. Your blog is splendid, I follow and read continuously the blogs that you share, they have some really important information. M glad to be in touch plz keep up the good work.
    Digital Marketing Course Pune

    ReplyDelete
  61. This is an awesome motivating article.I am practically satisfied with your great work.You put truly extremely supportive data. Keep it up. Continue blogging. Hoping to perusing your next post
    Know More Courses

    ReplyDelete
  62. Excellent post!!!. The strategy you have posted on this technology helped me to get into the next level and had lot of information in it.

    Python Online Training
    Python Certification Training
    Python Certification Course
    AWS Training
    AWS Course

    ReplyDelete
  63. Attend The Machine Learning course Bangalore From ExcelR. Practical Machine Learning course Bangalore Sessions With Assured Placement Support From Experienced Faculty. ExcelR Offers The Machine Learning course Bangalore.
    Machine Learning course Bangalore

    ReplyDelete
  64. Great post i must say and thanks for the information. Education is definitely a sticky subject. However, is still among the leading topics of our time. I appreciate your post and look forward to more.
    data analytics courses in mumbai

    ReplyDelete
  65. Nice information, valuable and excellent design, as share good stuff with good ideas and concepts, lots of great information and inspiration, both of which I need, thanks to offer such a helpful information here...digital marketing course bangalore

    ReplyDelete
  66. Nice information, valuable and excellent design, as share good stuff with good ideas and concepts, lots of great information and inspiration, both of which I need, thanks to offer such a helpful information here...digital marketing course bangalore

    ReplyDelete
  67. wonderful article. Very interesting to read this article.I would like to thank you for the efforts you had made for writing this awesome article. This article resolved my all queries.
    Data science Interview Questions
    Data Science Course

    ReplyDelete
  68. Nice information, valuable and excellent design, as share good stuff with good ideas and concepts, lots of great information and inspiration, both of which I need, thanks to offer such a helpful information here...digital marketing courses in bangalore

    ReplyDelete
  69. This Was An Amazing ! I Haven't Seen This Type of Blog Ever ! Thankyou For Sharing, data science courses

    ReplyDelete