Object-Oriented Programming

This page is using Python syntax, but all this information is applicable for any language that has OOP features, like Ruby, Java, Javascript, etc.

What Is It

Object-oriented programming is a programming paradigm that provides a means of structuring programs so that properties and behaviors are bundled into individual objects.[1]

Object oriented programming is a way to organize data and actions according to what they represent, like a person. These "prototypes" of things are called classes and instances of these classes are called objects.

For instance, you could create a generic Person class that has properties like name and age, and methods like say_hello, which you could instantiate an object for each new "person" you have in your program.

Classes

A class is a blueprint of what should exist within an instance. Classes contain properties and methods, where properties are pieces of information, and methods are functions. However, classes contain no data on their own (they can contain default information that will be passed down to an instance, but the key of classes are their ability to create instances).

In the following example, the Person class has name and age properties and a say_hello method, but they don't yet have a name or age since they have not been instantiated yet. When they are instantiated, the properties will be defined, and the methods will have some information they can use.

When a class is instantiated, it runs a constructor, which in Python is written as def __init__(self, ...) with all parameters passed in on instantiation as the arguments in the constructor.

class Person:
    def __init__(self, name: str, age: int):
        self.name = name
        self.age = age

    def say_hello(self):
        print(f"Hi!!! My name is {self.name}!")

    def greet(self, persons_name: str):
        print(f"Hello, {persons_name}!")

Class Attributes

Unlike properties, which are defined from instance to instance, class attributes are set to the value that will be used for all instances of said class. In our example above, we could set a class attribute of species to human, since we know that all instances of Person will be of the human species.

class Person:
    # Class Attribute
    species = "human"

    def __init__(self, name: str, age: int):
      # ... same as above

Abstract Classes and Methods[2-4]

An abstract class is a class that cannot be instantiated by itself, and can only be used as a parent class. An abstract method is similar in that the abstract method cannot be called on the class in which it was instantiated, but only in the child class. This abstraction is used to aid in maintenance of child classes or the function of methods or in a child class.

If an abstract method is declared in a superclass, subclasses that inherit from the superclass must have their own implementation of the method.[2]

For instance, if we defined an abstract class Shape, we would not be able to create an instance of Shape itself. We would need to create a child class, like Circle, and then instantiate that. Similarly, if we had a class of Dog and created an abstract method of bark, we would not be able to call bark on an instance of Dog; we would have to create a child class of Dog first, like Labrador, and define that method within that child class.

Python uses what is called abc or abstract base classes:

Abstract base classes are a form of interface checking more strict than individual hasattr() checks for particular methods. By defining an abstract base class, a common API can be established for a set of subclasses. This capability is especially useful in situations where someone less familiar with the source for an application is going to provide plug-in extensions, but can also help when working on a large team or with a large code-base where keeping track of all of the classes at the same time is difficult or not possible.[4]

Instances

An instance of a class will contain all new instance variables passed into it when instantiated, as well as all the class attributes defined by the class.

chelsea = Person('Chelsea', 23)
print(chelsea.age) i # prints 23
chelsea.say_hello() # prints "Hi!!! My name is Chelsea!"
bob = Person('Bob', 12)
print(bob.species)  # prints "human"
bob.say_hello()     # prints "Hi!!! My name is Bob!"

Instance values can be updated dynamically, as well. Let's say it was Bob's birthday today and we wanted to update their age by 1:

bob.age += 1
print(bob.age) # prints 13

Inheritance

One of the main concepts of object-oriented programming is the ability of child classes to inherit from a parent class. When a child class inherits from a parent class, it inherits all of the parent class's properties and methods.

Here, we have created an Adult child class using the parent class Person. We will receive all of Person's properties and methods, and we have added a new method to reflect the unique properties of an Adult.

# In Python, this shows that `Adult` "extends" the `Person` class
class Adult(Person):
    def pay_taxes(self):
        self.age += 1

jane = Adult('Jane', 35)
jane.say_hello() # prints "Hi!!! My name is Jane!"
print(jane.age)  # prints 35
jane.pay_taxes()
print(jane.age)  # prints 36

Extending Parent Methods aka Polymorphism

The child classes can also extend the functionality of the parent class by changing or overriding the parent class's method; you can also alter the child class's method by calling the parent class's method and using it differently. If the parent class changes a method, this will be propagated down to all child classes as well, unless it has been changed in that child class.

This is called polymorphism[6] and refers to the ability to call the same method on different child, sibling, or parent classes and have it perform different operations and/or return different results.

class Adult(Person):
    def pay_taxes(self):
        self.age += 1

    def say_hello(self):
        print(f"Greetings, I am {self.name}.")

    def greet(self):
        super().greet("there")

jane = Adult('Jane', 35)
jane.greet() # prints "Hello, there!"

Method Overloading

Note: this is not a feature in Python's implementation of OOP, so we will be using Java in this example[5]

Method overloading is when multiple instances of a method are created with differing types or amounts of arguments. When a method is called, which of the multiple versions of a method will be invoked is resolved by determining the different elements of the invoked method.

class Adder {
  static int add (int a, int b) {
    return a + b;
  }

  static int add (int a, int b, int c) {
    return a + b + c;
  }

  static double add (double a, double b) {
    return a + b;
  }
}

class TestOverloading1 {
  public static void main (String[] args) {
    System.out.println(Adder.add(11, 11));
    // Output: 22
    System.out.println(Adder.add(11, 11, 11));
    // Output: 33
    System.out.println(Adder.add(11.1, 11.1));
    // Output: 22.2
  }
}

References

  1. https://realpython.com/python3-object-oriented-programming/
  2. https://www.freecodecamp.org/news/object-oriented-programming-in-python/
  3. Basic explanation of abstract classes and methods
  4. https://pymotw.com/3/abc/
  5. https://www.javatpoint.com/method-overloading-in-java
  6. https://en.wikipedia.org/wiki/Polymorphism_(computer_science)
Incoming Links

Last modified: 202401040446