top of page
Search

Get Down With Object Oriented Programming II: Object Oriented Programming All Around Us

  • Writer: Allison Higgins
    Allison Higgins
  • 2 hours ago
  • 8 min read




ree


On my decade-long path to becoming a senior software engineer, I have been asked an astounding range of technical interview questions, in a variety of formats. I’ve done the take home assignments, brand name assessments, the panel vs me alone, and my personal favorite format, the technical conversation where I can share my experience and expertise, and it can be evaluated truthfully, based on my responses and follow up questions or suggestions. Some of these interviews and questions have been intense, but with practice and due diligence, I’ve built a routine to quickly switch from “job focused” engineer to “interview ready” engineer in approximately 6-8 weeks. While building this routine, I have repeatedly noticed that knowledge and mastery of data structures, algorithms, and how to apply them to object oriented programming consistently differentiates a candidate in a sea of applicants.


In a former role, I worked with an internal language and building platform that closely resembled Java and the Java Virtual Machine. As part of the interview for this role, I had to demonstrate a deep understanding of object oriented programming principles and unified modeling language diagrams. In my initial recruiter screening, I recalled a slight sense of panic as I was told that the interview would mostly consist of concepts I hadn’t reviewed or studied since undergrad. After some strategizing, I realized that I had to: 


  1. Refresh and practice these fundamentals through videos, examples, practice scenarios, and creating my own study guide


  1. Recall, use, and justify the application of object oriented programming fundamentals that were not necessarily required for my past full stack/front end development roles 



This blog will cover 

  1. Why does Object Oriented Programming Matter?

  2. Key Terms and Definitions 

  3. Implementing our Object Oriented Fundamentals to Make a School “fer” Wizards and Witches 

  4. Object Oriented Principles All Around Us

  5. Again, why does this matter? 

  6. Resources For Practice 




Why does Object Oriented Programming Matter?


There will always be a new, shiny technology that attracts a variety of investments and experts, but the underlying fundamentals and how to apply them will always be relevant. Understanding these principles eases the path to furthering your personal studies of data structures, algorithms, and eventually system design. These three are the core skills evaluated during a software engineer interview. These concepts are the foundations for building robust frontend/backend systems, data pipelines, and AI enablement, for any number of software needs across industries. 



Key Terms and Definitions: 


  • Object Oriented Programming (OOP)

    • Modeling a system as a collection of objects where each object represents some particular part of the system 

    • Objects have functions/methods and data 

    • Object provides a public interface to other code that wants to implement it, but its internal state is private 

    • These are purposefully abstracted because the other parts of the system do not need to know about them 


  • Inheritance 

    • Allowing one class to inherit features from another, promoting reusability in code 

      • also known as subclassing 


  • Polymorphism 

    • Objects of a different type can be accessed through the same interface

    • Each type can provide its own independent implementation of this interface

  • Encapsulation

    • Coupling data and methods into a single object to protect internal logic 

    • Allows a dev to change the internal implementation of an object, without having to update all the code that uses it 

    • Little firewall 


  • Abstraction

    • Hiding complex details while exposing only necessary functionalities to external users 

    • Data abstraction 

    • Process abstraction 

    • Difference between abstract classes and interfaces is that interfaces do not contain any method implementations, only the method signatures 

    • Visibility can also be established using key keywords private, protected, and public

      • can also be indicated by an underscore 



Let’s Implement our new OOP Knowledge to Build a school “fer” wizards and witches


We will start by modeling a school with objects representing students

  • Class name: Student

    • Attributes: name, house, and year

    • Actions: introduceToClass, introduceToFriends, castSpell 

  • This definition lists the data and methods the student object has 


Alone, our student class doesn’t do anything 

  • This is the template to create a student, but to create an instance of a student, we must use a constructor 

  • Usually the constructor is included with the class definition and has the same name as the class it’s in 

  • Here we’d call it with the properties we set previously: name, house, and year

  • Now we can create several different students 

  • Generation is indicated with the “new” key word 

    • student Hermione = new Student(“Hermione”, Gryfindoor, 4);


Let’s Implement a method - introduceToClass

  • Hermione.introduceToClass();


But what if we tried ProfessorSnape.introduceToClass? 

  • Immediate error because the object ProfessorSnape doesn’t exist in our school object model yet. Let’s fix it. 

  • Student ProfessorSnape = new Student(“Professor Snape”, Slytherin, 18)


Professor Snape is NOT a student, so he would need a professor class for instantiation 

  • Class name: Professor 

    • Attributes: name, subject

    • Actions: introduceToClass

  • Does this look incredibly similar to the student class?  


Addressing the commonality of student and professor classes 

  • Both have attribute name and a method for introducing themselves 

  • On a core level data wise, they are the same “kind” of object, just slightly different implementations 


We can better express this with a superclass 

  • Class name: Person 

    • Attributes: name 

    • Methods: introduceToClass() 


To implement specific instances of person, such as student or professor, we use the key word extends 

  • In OOP, extends, allows for use of custom properties and methods particular to the object you want to create

  • The method introduceToClass can also be customized in a student instance or a professor instances 


Let’s implement a new constraint in our school universe:

  • "Students can only take advanced defense against the dark arts after year 4"

  • This new constraint can be defined specifically in the student class 

  • If this constraint changes, for example, to require parental permission as well, we need to update this condition everywhere in our school universe where this check is performed 

    • Better design to create a custom canStudy() method on student class that implements this logic in one place.




Object Oriented Programming All Around Us 


JavaScript supports core object-oriented programming principles through its flexible and dynamic nature.


  • Abstraction: Achieved using functions, classes, and modules that hide complexity and expose only essential interfaces.

  • Encapsulation: Implemented through closures, which allow functions to retain access to variables from their parent scope even after that scope has finished executing.

  • Polymorphism: Enabled by method overriding and overloading, allowing objects to define different behaviors for the same interface.

  • Inheritance: Achieved via the prototype chain, where objects can delegate behavior to other objects. Unlike traditional class-based inheritance, JavaScript’s approach is delegation-based — objects can ask their “prototype” to perform tasks they don’t handle themselves.


JavaScript Closure Example: 

ree
  • makeFunction() defines a variable count and returns innerFunction.

  • Even after makeFunction() has finished running, innerFunction still “remembers” the variable count from its parent scope — this is the closure in action.

  • Each call to counter() updates and logs the preserved count value.




Python also supports object oriented programming principles despite being considered a functional language.

  • Abstraction: Python achieves abstraction using abstract base classes (ABCs) from the abc module.Abstract methods and properties define an interface that subclasses must implement, hiding unnecessary implementation details and focusing on essential behavior.

  • Encapsulation: Controlled access to class attributes through access specifiers (_protected, __private) and getter/setter methods. This ensures that internal data is shielded from direct external modification.

  • Polymorphism: Supports runtime polymorphism, where the same method name can exhibit different behaviors depending on the object calling it (e.g., method overriding).

  • Inheritance: Enables reusability and structure through different forms:

    • Single Inheritance: One child inherits from one parent.

    • Multiple Inheritance: A child inherits from multiple parents.

    • Multilevel Inheritance: A child inherits from a parent, which itself is a child of another class.

    • Hierarchical Inheritance: Multiple child classes inherit from a single parent.


Python Abstraction and Inheritance In-Depth with Examples


  • Abstraction

    • ree
    • Animal is an abstract base class (inheriting from ABC).

    • The @abstractmethod decorator means any subclass must implement make_sound(), or else it can’t be instantiated.

    • This enforces a contract for all animals — every animal must define how it makes a sound.


  • Single Inheritance

    • ree

    • Dog inherits from Animal → this is single inheritance (one parent, one child).

    • The attribute __name is encapsulated (made private with double underscores).

    • Access is controlled using getter (get_name) and setter (set_name) methods.

    • make_sound() is implemented (overriding the abstract method from Animal), showing polymorphism — the same method name can have different behaviors across subclasses.


  • Multiple Inheritance

    • ree
    • GuardDog inherits from three classes: CanRun, CanBark, and Dog.

    • This is multiple inheritance — one class inherits from more than one parent.

    • As a result, GuardDog can:

    • Use run() from CanRun

    • Use bark() from CanBark

    • Use make_sound() and encapsulated methods from Dog

    • This allows GuardDog to combine behaviors from multiple sources — a hallmark of multiple inheritance.



  • Multilevel Inheritance

    • ree
    • Puppy inherits from Dog, which inherits from Animal.

    • This is multilevel inheritance — a chain of inheritance across multiple levels.

    • Puppy overrides make_sound() again (now “Yip!”), showing runtime polymorphism — the version of the method that runs depends on the object’s actual type at runtime.


  • Hierarchal Inheritance

    • ree

    • Both Dog and Cat inherit from the same parent (Animal).

    • This is hierarchical inheritance — one parent, multiple children.

    • Each subclass provides its own version of make_sound().





Although Rust isn’t traditionally classified as an object-oriented language, it implements many object oriented programming concepts in its own way.

  • Abstraction: Rust achieves abstraction primarily through generics and traits:

    • Generics allow code to be written for multiple data types without repetition.

    • Trait bounds specify what behaviors a type must implement, allowing for shared interfaces similar to abstract classes or interfaces in other languages. 

  • Encapsulation: Rust uses modules and the pub keyword to control visibility:

    • By default, all items are private to their module.

    • The pub keyword explicitly exposes functions, structs, and methods to other parts of the program.

    • Implementation blocks (impl) define methods for types, similar to how classes encapsulate behavior in object oriented programming.

  • Inheritance: Rust doesn’t have traditional class inheritance. Instead, it encourages composition and trait-based behavior sharing.

    • The closest equivalent to inheritance is macros, which enable code reuse and pattern expansion across multiple types or modules — somewhat like metaprogramming templates.

  • Polymorphism: Rust supports bounded parametric polymorphism, meaning:

    • Functions and data structures can work with any type (T) as long as that type satisfies certain trait bounds.

    • This is polymorphism via traits, not class hierarchies — ensuring compile-time safety.



Macros and Metaprogramming in Rust

  • A macro in Rust is code that writes other code — a form of metaprogramming

  • The most common example is println!(), a function-like macro that expands to output code at compile time.

  • Macros allow Rust to implement powerful code reuse and abstraction patterns without runtime overhead.

ree





Go is not a class-based object-oriented language like Java or Python, but it supports object oriented principles through its own unique design choices — emphasizing simplicity, composition, and interfaces rather than traditional inheritance.


  • Abstraction: In Go, interfaces provide abstraction. An interface defines a set of method signatures — any type that implements those methods automatically satisfies the interface, without explicitly declaring it. This enables flexible, decoupled design.

  • Encapsulation: Go controls visibility using capitalization. This replaces explicit access modifiers like private or public.

    • Identifiers (functions, methods, types) that start with an uppercase letter are exported (public).

    • Identifiers that start with a lowercase letter are unexported (private) to their package.

  • Inheritance (via Composition): Go does not support classical inheritance. Instead, it uses composition, where a struct contains another struct to reuse its fields and methods. This pattern is often described as “has-a” instead of “is-a” relationship.

  • Polymorphism: Go supports polymorphism through interfaces. Different types can implement the same interface and be used interchangeably where that interface is expected.



Structs in Go

ree
  • Collection of members of different data types into a single variable 

  • This is useful for grouping together data to create/store records 

  • To access the members of a struct, use dot notation 




Again Why Does this Matter 


There will always be a new, shiny technology that attracts a variety of investments and experts, but the underlying fundamentals and how to apply them will always be relevant. Understanding these principles eases the path to furthering your personal studies of data structures, algorithms, and eventually system design. These three are the core skills evaluated during a software engineer interview — but more importantly, they are the same skills that form the backbone of everything we build in this field. Understanding object-oriented programming (OOP) fundamentals is not just an academic exercise; it’s the foundation for designing and maintaining robust systems — whether you’re architecting a frontend application, a backend service, a data pipeline, or an AI-driven platform. OOP principles such as abstraction, encapsulation, inheritance, and polymorphism enable engineers to write code that is modular, maintainable, and scalable across any domain. By mastering these concepts, engineers at any level — from junior developers to senior executives — can better navigate new technologies with confidence. The syntax and tools may change, but the mental models stay the same.



Resources for Practice 


JavaScript 



Python 



Rust 



Golang



General Programming 


 
 
 

Comments


© 2024 by Kolor Koded Studios. Powered and secured by Wix

bottom of page