Introduction
Ruby is a dynamic, interpreted, object-oriented programming language developed by Yukihiro ("Matz") Matsumoto at some point in the mid-1990s, with its first stable release in 1995. According to the creator of Ruby, it is highly influenced by Perl, Smalltalk, Ada, and Lisp. The influence of these languages on Ruby allows it to embrace various programming paradigms, such as functional, object-oriented, and imperative, with dynamic typing (referred to as duck typing in popular culture) and automatic memory management.
Being an interpreted scripting language, Ruby has the ability to make system calls directly, and has a long list of useful string operations where variable declaration and variable type are not required. Ruby wholly embraces object-oriented programming because everything in Ruby is an object. Ruby has a long list of keywords that make many operations a piece of cake. This means you can do more with less code.
Whether you are a newbie to the world of programming, or an experienced developer in other languages who is tired of the compilation processes, extra declarations, and the keywords of other languages, Ruby will be a revelation from the point of view of your productivity.
With all these characteristics, Ruby gives developers an enriching experience, making programming productive and fun. In addition to Ruby being a fantastic programming language, the Ruby community is also very friendly and supportive.
Key Features of Ruby
A number of key features of the Ruby language make it really unique in terms of working with it. It has very neatly assimilated the best features of many programming languages. Here are a few features of Ruby that make it a delight to program with:
- Object-oriented
- Interpreted language
- Duck typing and dynamic typing
- Multi-paradigm language
- Reflection
- Metaprogramming
Object-Oriented
Ruby is thoroughly object-oriented, and objects are the basic building block of a Ruby program. Every value in Ruby is an object, even data types such as strings, numbers, and Booleans: everything is an object. This means that every object is part of a class that gives access to a wide range of methods to do incredible things. Each class is also an object in Ruby. Here's an example:
class Fruit #code end
The preceding code defines the Fruit
class. The following code shows that two new objects, fruit1
and fruit2
, are derived from the Fruit
class:
fruit1 = Fruit.new fruit2 = Fruit.new
Interpreted Language
Ruby is an interpreted language, meaning that it's ready to run the program as soon as you finish typing. Unlike programming languages such as C++, Java, and Objective-C, which require code to be compiled before running, this is not the case with Ruby. Look at this example:
print "Hello World"
This code will immediately print Hello World
, as follows:
Hello World
Duck Typing and Dynamic Typing
Dynamic typing means a variable can refer to objects of various types when the program is executed. There is no type checking in Ruby. Duck typing is a principle that denotes that an object is based on the value assigned to it rather than the type of variable. The underlying rule here is: "If it walks like a duck and quacks like a duck, then it must be a duck." Here's an example:
x= [:a, :b, :c] x.map(&:to_s) # => ['a', 'b', 'c']
The preceding example illustrates how the x
variable responds to map
and returns the expected object. This means that the x
variable here is considered an array.
Multi-paradigm Language
While languages are focused on one type of programming paradigm, besides being object-oriented, Ruby also allows procedural and functional styles of programming. The procedural paradigm refers to an instance where procedure calls are interpreted as function calls. However, functions do not exist in Ruby, and, therefore, methods can be created outside classes. Look at this example:
self # => main def method1 "John is developing a program." end def method2 "Jane is developing another program." end method1 # => "John is developing a program." method2 # => "Jane is developing another program."
Here, method1
and method2
are defined outside the classes; however, they are still a part of the main
object.
Additionally, Ruby also features the functional style of programming, meaning it largely revolves around functions. Consider the following example:
def ruby_method(obj) obj - 1 end print ruby_method(5) => 4
Here, the ruby_method
always stores the result of the object passed as an argument, subtracting 1.
Reflection
Reflection in Ruby makes it very easy to understand what's happening at runtime because you can get a lot of information, such as class methods, inheritance hierarchies, and all the living objects in your running program. Here's an example:
class Box def hello "hello" end end # without reflection obj = Box.new obj.hello # with reflection class_name = "Box" method_name = :hello obj = Object.const_get(class_name).new obj.send method_name
This shows that we can inspect every element of the code.
Metaprogramming
Ruby supports metaprogramming, which is a technique that helps you to write code that creates code on its own. This means it is able to create methods and classes dynamically. With metaprogramming, you can write methods and classes at runtime, which helps us to maintain a Don't Repeat Yourself (DRY) and maintainable code base. Here's an example:
['one', 'two', 'three'].each do |num| define_method(num) do num.upcase end end one # => "ONE" two # => "TWO" three # => "THREE"
The preceding code shows that we can make changes to the core Array
class at runtime and modify it as required.