Oriented-Object programming

Object-Oriented Programming (OOP) 🧸 is a paradigm emphasizing the use of objects to encapsulate both data and code.

It often means a lot more code to write, but it's supposed to improve reusability and modularity. OOP does not apply to all problems.

At the very least, it can make the code easier to implement and maintain, especially in teams, as we can break the code into small junks and code them, roughly one at a time.

Some common concepts are:

  • Encapsulation
  • Inheritance
  • Polymorphism
  • Abstraction
  • Open recursion

Classes and objects

A class can be seen as a template/blueprint πŸ–¨οΈ to create objects. It defines an abstract concept, such as a person or an animal... while an object is concrete, for instance, the person "John Doe" πŸͺ†.

Class and object

πŸ—ΊοΈ The process of creating an object from a class is called Instantiation. Objects are commonly called instances.

Attributes

A class has properties called attributes that are used to store data. For instance, each person has a name.

class Person {
    public String name;
}

Methods

A class also has methods which are functions that can access attributes or other methods usually by using this/self/....

class Person {
    [...]
    
    public void changeName(String name) {
        this.name = name; // set the attribute "name" to...
    }
}

➑️ In some languages, this/... is optional when implicit.

Constructors

We are usually constructors to instantiate a new object, which usually means initializing the attributes. A constructor is a method.

class Person {
    public String name;
    
    public Person(String name) {
        this.name = name; // init attribute "name"
    }
}

Instantiation is done by calling the constructor. Some languages use the new keyword, some don't.

Person johnDoe = new Person("John Doe");
// johnDoe.name is equal to "John Doe"

Members

Attributes and methods are usually called members. There are two categories of members: instance members and class members.

The former are the usual members. The latter are members of the class, meaning that

  • every instance has the same value for an attribute
public static final String DEFAULT_NAME = "John DOE"; // java
  • we don't need an instance to access a member
String defaultName = Person.DEFAULT_NAME;

Access control

Classes, methods, attributes, and many other concepts have some form of access control commonly done using a visibility modifier.

For instance, C# has a modifier called internal only allows some classes in the same "output file" (assembly file) to use this class.

internal class XXX {} // same assembly only

Iceberg Principle: this is a commonly used principle of only exposing a small part to the outside, while keeping internals private. The goal is to minimize the impact on others when adding/updating/removing members or rewriting internals.

Common modifiers are:

  • Java: private, protected, public, <none> (package-private)
  • C++: private, protected, public
  • PHP: private, protected, public
  • C#: private, protected, public, internal
  • ...

➑️ Python devs are using naming conventions to determine the visibility, while in Ruby, modifiers are present but not enforced...


Inheritance

Inheritance allows classes to be based on another class. They will inherit attributes and methods, and may be able to:

  • ✍️ Add new methods and attributes
  • πŸ“ Change the behavior of existing methods (override)

The ancestor is usually called:

  • parent
  • superclass
  • base class

The inheritor is usually called

  • child/heir
  • subclass
  • derived class

πŸ‘‰ Most languages have a root class, such as Object in Java.

πŸ‘‰ Many languages forbid multiple inheritance (multiple parents).

Polymorphism

Polymorphism refers to the ability to treat objects of child classes as objects of their parent class.

class A {}           // A is a parent class of B and C
class B extends A {} // B is a child class of A
class C extends A {} // C is a child class of A
// usual behavior of a child class
B b = new B();       // Stores as B
b.someMethodInA();   // Calls B's method (if overridden)
b.someMethodInB();   // Calls B's method

As B and C inherit from A, they can be stored in a variable of type A.

A a = new B();       // Stores as A
a.someMethodInA();   // Calls B's method (if overridden)

Liskov substitution principle refers to the fact that regardless of the child class we use, the program should work as expected.

A a = new B(); // if it works with B, then it works with C

πŸ‘» To-do πŸ‘»

Stuff that I found, but never read/used yet.