The Simple Pillars of OOP
Polymorphism does not have to be a scary word
Abstraction, encapsulation, inheritance, and polymorphism are the four pillars on which object oriented programming (OOP) is built. Following these principles will lead to clean, reusable, and modular code but your first need to understand what they mean. Initially these terms can be intimidating but with simple examples you will quickly wrap you mind around the concepts.
Abstraction refers to hiding the details of implementation into reusable methods, classes, or modules. This way the user or programmer does not need to understand all the little details but just the ideas of what a particular piece of code is doing. For example, say you want fried chicken for dinner, first you look up a recipe, then buy all your ingredients, prep the chicken, preheat the oven, pan fry the chicken, and finally eat it. An abstraction would be to buy fried chicken from Popeyes. When you buy the chicken all the prep and cooking steps are done behind the scene and the user doesn't have to worry about those details.
def make_fried_chicken
look_up_recipe
buy_ingredients
prep_chicken
preheat_oven
pan_fry
endFigure 1: Abstraction of cooking fried chicken into a method
Encapsulation is defined as “the action of enclosing something in or as if in a capsule”. In programming this refers to private class methods that are not accessible from outside of the class. Much luck a capsule of tylenol encapsulates various ingredients, the user does not measure out the quantity of each ingredient, mix them together, and then seal them in a capsule as these are private methods. The user only has to know how to take a capsule.
class Tylenol def create_pill
measure_ingredients
mix_ingredients
seal_ingredients_in_capsule
end private def measure_ingredients
...
end def mix_ingredients
...
end def seal_ingredients_in_capsule
...
endendFigure 2: Encapsulation tylenol pill via private methods
In the above figure the only public method of Tylenol is create_pill
and all other methods are private. These methods are not exposed to an outside user of the class but are accessible within the class.
Inheritance means to derived traits from a parent much like you inherit traits such as your hair or eye color from your parents. In code, classes can inherit methods and fields from a parent class or use composition to pull from several classes. For example, the Dog
class in Figure 3 inherites the eat
and sleep
method from Animal
and defines its own method speak.
class Animal
def eat
...
end def sleep
...
end
endclass Dog < Animal
def speak
puts "bark bark"
end
endFigure 3: Dog class inherited the methods from Animal
Polymorphism is a combination of the latin word “poly” meaning many and “morph” meaning forms. This means classes in the same inheritance chain can can all be used the same, that is they respond to the same messages without error. In addition, inherited methods and fields can be overwritten to give them new behavior or a different state. For example, you may have two dogs but they each have their own name, breed, eye color, and etc.
class Dog
attr_reader :name, :breed def initialize(name:, breed:)
@name = name
@breed = breed
end def speak
puts "bark bark"
end
enddog_1 = Dog.new(name: "Rover", breed: "Golden Retriever")
dog_2 = Dog.new(name: "Hunter", breed: "Dachshund")dog_1.name
# "Rover"
dog_2.name
# "Hunter"Figure 4: Polymorphism of the Dog class via dog_1 and dog_2
From the code snippet in Figure 4 you can see that dog_1
and dog_2
are both instances of the Dog
class but they have different names. This is a basic use of polymorphism but one could also add/modify methods.