Object Oriented Programming Interview Questions Cheat Sheet
Read at your own pace. Code execution, quizzes, progress tracking, and the AI tutor are available in the interactive view with JavaScript enabled.
Introduction
When preparing for an interview for a software engineering position, you should always keep in mind that besides knowing the certain technology you are interviewing for, you should be well-prepared with some basic Object-Oriented programming theory.
Object-Oriented programming principles are the fundamental building block of every modern programming language or concept. The most widely used programming languages are Object-Oriented, including Java, Python, C#, C++ etc. They all implement the basic OOP principles, so when working with an Object-Oriented language, you should possess strong knowledge of the OOP basic theoretical principles.
When interviewing, your tech interviewer will most probably ask you a couple of basic OOP questions, in order to verify that you have the necessary fundamental knowledge and that you understand the principles of OOP, no matter what experience, or knowledge in a certain tech stack you have.
In this article, we are going to ask and answer 15 of the most important OOP interview questions to prepare you for your next interview.
OOP basics: Concepts, Classes and Objects
1. What is Object-Oriented Programming?
Object-Oriented Programming is a programming paradigm defined using objects instead of only functions and methods. The objects contain data, called attributes, and methods that provide the logic or supporting code for a given logic unit. Some of its main principles include inheritance, polymorphism, encapsulation, and abstraction.
2. What are some advantages of Object-Oriented Programming
- Problems of any level of complexity can be supported
- Highly complex problems can be handled
- It provides an efficient mechanism for code reuse using inheritance which reduces redundancy
- It provides a mechanism for hiding data
- It is based on a bottom-up approach
- It offers flexibility through polymorphism
- It improves the maintainability of the code
3. What are the main principles of OOPs?
Object-Oriented Programming has four main principles, and they are the following: - Inheritance - Encapsulation - Polymorphism - Data Abstraction

4. What is a class?
A class defines the definition of an object, and thus, it can be used to create objects at runtime. It provides the data structure, initial values for the attributes, and methods that provide the logic for the intended behavior of the object.
class Test {
member variables // class body
methods
}
public class Test {
// member variables
// methods
}
class Test {
// member variables
// methods
}
class Test:
# member variables
# methods
class Test {
// member variables
// methods
};
type Test struct {
// member variables
}
// methods
The class does not consume memory at runtime.
A class refers to a logical entity- for example, a vehicle may be defined as a class.
5. What is an object?
An object refers to the runtime instance created from the class during program execution. Objects can refer to real-world entities that have attributes and methods (logic) to support the behavior. Objects consume memory space only after they are initialized.
//Declaring and Initializing an object
Test t = new Test();
// Declaring and initializing an object
let t = new Test();
# Declaring and initializing an object
t = Test()
// Declaring and initializing an object
Test t;
// Declaring and initializing an object
Test t = new Test();
// Declaring and initializing an object
t := Test{}

6. What is a constructor?
A constructor is a method that is used for initializing the objects, from their classes. They are special types of methods that have the same name as the class, and they can be parameterless or initialize values for the attributes of the object.
There are three types of constructors:
– Default Constructor – Without parameters
– Parametric Constructor – Includes parameters to create a new instance of a class and also pass arguments simultaneously to provide different values to the distinct objects at the time of their creation
– Copy Constructor – Creates a new object as a copy of an existing object
```java
public class Main {
public static void main(String[] args) {
Test ob1 = new Test();
Test ob2 = new Test(123, "TestPerson");
System.out.println(ob1.Id);
System.out.println(ob1.Name);
System.out.println(ob2.Id);
System.out.println(ob2.Name);
}
}
class Test {
int Id;
String Name;
//Parameteric constructor with 2parameters
Test(int id, String name) {
this.Id = id;
this.Name = name;
}
// Default Constructor
public Test() {
}
}
```
```javascript
class Test {
constructor(id, name) {
this.id = id;
this.name = name;
}
// The 'constructor' acts as a default constructor when not sending parameter value
}
let ob1 = new Test();
let ob2 = new Test(123, "TestPerson");
console.log(ob1.id);
console.log(ob1.name);
console.log(ob2.id);
console.log(ob2.name);
```
```python
class Test:
def __init__(self, id=None, name=None):
self.id = id
self.name = name
ob1 = Test()
ob2 = Test(123, "TestPerson")
print(ob1.id)
print(ob1.name)
print(ob2.id)
print(ob2.name)
```
```cpp
#include<iostream>
#include<string>
class Test {
public:
int Id;
std::string Name;
Test(int id, std::string name) {
Id = id;
Name = name;
}
Test(){}
};
int main() {
Test ob1;
Test ob2(123, "TestPerson");
std::cout << ob1.Id << std::endl;
std::cout << ob1.Name << std::endl;
std::cout << ob2.Id << std::endl;
std::cout << ob2.Name << std::endl;
}
```
```csharp
using System;
class Test
{
public int Id;
public String Name;
// Parameteric constructor with 2 parameters
public Test(int id, String name)
{
this.Id = id;
this.Name = name;
}
// Default Constructor
public Test() {}
}
class Program
{
static void Main(string[] args)
{
Test ob1 = new Test();
Test ob2 = new Test(123, "TestPerson");
Console.WriteLine(ob1.Id);
Console.WriteLine(ob1.Name);
Console.WriteLine(ob2.Id);
Console.WriteLine(ob2.Name);
}
}
```
```go
package main
import "fmt"
type Test struct {
Id int
Name string
}
func main() {
ob1 := &Test{}
ob2 := &Test{123, "TestPerson"}
fmt.Println(ob1.Id)
fmt.Println(ob1.Name)
fmt.Println(ob2.Id)
fmt.Println(ob2.Name)
}
```
```java
public class Main {
public static void main(String[] args) {
Test ob1 = new Test();
Test ob2 = new Test(123, "TestPerson");
System.out.println(ob1.Id);
System.out.println(ob1.Name);
System.out.println(ob2.Id);
System.out.println(ob2.Name);
}
}
class Test {
int Id;
String Name;
//Parameteric constructor with 2parameters
Test(int id, String name) {
this.Id = id;
this.Name = name;
}
// Default Constructor
public Test() {
}
}
```
```javascript
class Test {
constructor(id, name) {
this.id = id;
this.name = name;
}
// The 'constructor' acts as a default constructor when not sending parameter value
}
let ob1 = new Test();
let ob2 = new Test(123, "TestPerson");
console.log(ob1.id);
console.log(ob1.name);
console.log(ob2.id);
console.log(ob2.name);
```
```python
class Test:
def __init__(self, id=None, name=None):
self.id = id
self.name = name
ob1 = Test()
ob2 = Test(123, "TestPerson")
print(ob1.id)
print(ob1.name)
print(ob2.id)
print(ob2.name)
```
```cpp
#include<iostream>
#include<string>
class Test {
public:
int Id;
std::string Name;
Test(int id, std::string name) {
Id = id;
Name = name;
}
Test(){}
};
int main() {
Test ob1;
Test ob2(123, "TestPerson");
std::cout << ob1.Id << std::endl;
std::cout << ob1.Name << std::endl;
std::cout << ob2.Id << std::endl;
std::cout << ob2.Name << std::endl;
}
```
```csharp
using System;
class Test
{
public int Id;
public String Name;
// Parameteric constructor with 2 parameters
public Test(int id, String name)
{
this.Id = id;
this.Name = name;
}
// Default Constructor
public Test() {}
}
class Program
{
static void Main(string[] args)
{
Test ob1 = new Test();
Test ob2 = new Test(123, "TestPerson");
Console.WriteLine(ob1.Id);
Console.WriteLine(ob1.Name);
Console.WriteLine(ob2.Id);
Console.WriteLine(ob2.Name);
}
}
```
```go
package main
import "fmt"
type Test struct {
Id int
Name string
}
func main() {
ob1 := &Test{}
ob2 := &Test{123, "TestPerson"}
fmt.Println(ob1.Id)
fmt.Println(ob1.Name)
fmt.Println(ob2.Id)
fmt.Println(ob2.Name)
}
```
Question 1
The classes' memory consumption depends on the number of attributes.
Inheritance and Polymorphism
7. What are access modifiers?
Access modifiers specify the scope of accessibility of a data member, method, constructor or class. Depending on the language there can be various modifiers, but there are three main and shared betweem all of the OOP languages, that are fundamental.
Access Modifier Definition public No restricted access, from same assembly (or package) or a referencing one private Access limited to the containing type (class or struct) protected Access limited to the containing class or derived classes8. Explain the concept of inheritance
Inheritance is one of the main features of object-oriented programming which allows classes to inherit properties and methods from other classes. This helps improve code reuse.
For example, we can have a base class called animal, that may define the common properties shared by all animals. Then, we can define child classes such as: mammals, reptiles, etc. that will inherit the common attributes of all animals but will be able to define their own specific attributes and methods.

However, there are some limitations of the process of inheritance, for example, it requires more processing time for the programs as it has to navigate various classes during execution. Also, due to inheritance, the parent and child class are tightly coupled. When any changes are needed in the logic, it may require changes in both parent and child classes.
If the inheritance is not correctly implemented, it can lead to undesired results.
9. What are the various types of inheritance?
The various types of inheritance include:
- Single inheritance - A class inherits the properties of a single parent class.
Class A{
//parent class code
}
Class B extends A {
//child class code
}
public class A
{
//parent class code
}
public class B : A
{
//child class code
}
class A:
#parent class code
pass
class B(A):
#child class code
pass
class A {
// parent class code
};
class B : public A {
// child class code
};
class A {
//parent class code
}
class B extends A {
//child class code
}
type A struct {
//parent struct (similar to class in Go) code
}
type B struct {
A //embedding (similar to inheritance in Go)
//child class code
}
- Multiple inheritances - An object or class can inherit features from more than one parent object or parent class. Not supported in all programming languages.
- Multi-level inheritance - One class has more than one parent class but at different levels of inheritance
Class A{
//parent class code
}
Class B extends A {
//your code
}
Class C extends B {
//your code
}
class A {
// parent class code
}
class B extends A {
// your code
}
class C extends B {
// your code
}
class A:
# parent class code
pass
class B(A):
# your code
pass
class C(B):
# your code
pass
class A {
// parent class code
};
class B : public A {
// your code
};
class C : public B {
// your code
};
public class A
{
// parent class code
}
public class B : A
{
// your code
}
public class C : B
{
// your code
}
type A struct {
// parent class code
}
type B struct {
A // your code
}
type C struct {
B // your code
}
- Hierarchical inheritance - One parent can have one or more child/sub/derived classes
Class A{
//parent class code
}
Class B extends A {
//child class code
}
Class C extends A {
//child class code
}
class A{
//parent class code
}
class B extends A {
//child class code
}
class C extends A {
//child class code
}
class A:
#parent class code
pass
class B(A):
#child class code
pass
class C(A):
#child class code
pass
class A{
//parent class code
};
class B : public A {
//child class code
};
class C : public A {
//child class code
};
class A
{
//parent class code
}
class B : A
{
//child class code
}
class C : A
{
//child class code
}
type A struct {
// parent class code
}
type B struct {
A // embedding parent "class"
// child class code
}
type C struct {
A // embedding parent "class"
// child class code
}
- Hybrid inheritance - Combination of more than one type of inheritance in a single program
A
/
B C
/
D E
10. What is polymorphism?
Polymorphism is a significant feature of object-oriented programming that represents the ability for existence in multiple forms. A single interface can be implemented in multiple ways by providing various definitions and implementations.
In Object-Oriented Programming languages, there are two types of polymorphism: 1. Static Binding (or Compile time) Polymorphism, e.g., Method Overloading
static int add(int a, int b){
return a+b;
}
static double add( double a, double b){
return a+b;
}
function add(a, b){
return a+b;
}
def add(a, b):
return a+b
int add(int a, int b){
return a+b;
}
double add( double a, double b){
return a+b;
}
public static int Add(int a, int b){
return a+b;
}
public static double Add(double a, double b){
return a+b;
}
func addInt(a int, b int) int {
return a + b;
}
func addFloat64(a float64, b float64) float64 {
return a + b;
}
- Dynamic Binding (or Runtime) Polymorphism, e.g., Method overriding
```java
public class Main {
public static void main(String[] args)
{
iPhone mess = new iPhone();
mess.sms();
}
}
class Phone{
void message(){
System.out.println("Message");
}
}
//Extending the Phone class
class iPhone extends Phone{
//Overriding message() of Phone class
void sms(){
System.out.println("iPhone Message");
}
}
```
```javascript
class Phone{
message(){
console.log("Message");
}
}
//Extending the Phone class
class iPhone extends Phone{
//Overriding message() of Phone class
sms(){
console.log("iPhone Message");
}
}
let mess = new iPhone();
mess.sms();
```
```python
class Phone:
def message(self):
print("Message")
#Extending the Phone class
class iPhone(Phone):
#Overriding message() of Phone class
def sms(self):
print("iPhone Message")
mess = iPhone()
mess.sms()
```
```cpp
#include <iostream>
class Phone {
public:
void message() {
std::cout << "Message" << std::endl;
}
};
//Extending the Phone class
class iPhone : public Phone {
public:
//Overriding message() of Phone class
void sms() {
std::cout << "iPhone Message" << std::endl;
}
};
int main() {
iPhone mess;
mess.sms();
return 0;
}
```
```csharp
public class Phone
{
public virtual void Message()
{
Console.WriteLine("Message");
}
}
//Extending the Phone class
public class iPhone : Phone
{
//Overriding Message() of Phone class
public override void Message()
{
Console.WriteLine("iPhone Message");
}
}
public class Program
{
public static void Main()
{
iPhone mess = new iPhone();
mess.Message();
}
}
```
```go
package main
import "fmt"
type Phone struct {}
func (p Phone) message() {
fmt.Println("Message")
}
//Extending the Phone struct
type iPhone struct {
Phone
}
//Overriding message() of Phone struct
func (p iPhone) sms() {
fmt.Println("iPhone Message")
}
func main() {
mess := iPhone{}
mess.sms()
}
```
Association and Composition
Common Follow-up: Association, Aggregation and Composition
Interviewers sometimes ask about the different ways objects can be related to one another. These are usually described as HAS-A relationships.
Relationship Meaning Example Association One class knows about or uses another class ATeacher teaches a Student
Aggregation
One class has another class, but the contained object can live independently
A Department has Professor objects
Composition
One class strongly owns another class, and the contained object depends on it
A House has Room objects
A simple way to remember the difference is:
- Association: uses or communicates with
- Aggregation: has, but does not fully own
- Composition: has and owns the lifecycle
For example, if a Library is deleted, the Book objects may still exist somewhere else. That is usually aggregation. But if an Order is deleted, its OrderItem objects usually do not make sense by themselves. That is closer to composition.

```java
import java.util.*;
class Book {
String title;
Book(String title) {
this.title = title;
}
}
class Library {
// Aggregation: books can exist outside the library
private List<Book> books;
Library(List<Book> books) {
this.books = books;
}
}
class OrderItem {
String productName;
int quantity;
OrderItem(String productName, int quantity) {
this.productName = productName;
this.quantity = quantity;
}
}
class Order {
// Composition: order owns its order items
private List<OrderItem> items = new ArrayList<>();
void addItem(String productName, int quantity) {
items.add(new OrderItem(productName, quantity));
}
}
```
Question 2A
Which relationship best describes a class that strongly owns another object, where the contained object usually should not exist independently?
Question 2
Which of the following are inheritance types?
Overloading, Encapsulation and Abstraction
11. What is method or operator overloading?
The method overloading is a feature of object-oriented programming in which multiple methods can have the same method name with different arguments. The call to the method is resolved based on the arguments.
Operator overloading means that depending on the arguments passed, the operators’ behavior can be changed. However, it works only for user-defined types.
12. What do you know about encapsulation?
Encapsulation is an important feature of object-oriented programming which allows the binding of the data and the logic together in a single entity. It also allows the hiding of data, so it is also known as a combination of data-hiding and abstraction.
Encapsulation can be achieved by performing two steps:
- Declaring the variables of a class as private
- Providing public setter and getter methods to modify and view the variables' values
13. What is an abstraction?
Abstraction shows only the necessary details to the client of an object. This means that it shows only required details for an object, not the inner constructors of an object.
For example, if you turn on the TV, you do not need to know the inner mechanism needed to do that, so whatever is needed to turn it on will be shown using an abstract class.
You can achieve abstraction in two ways:
- Using Abstract Class Abstract Class is a class which is declared with an abstract keyword and cannot be instantiated. Few pointers to create an abstract class:
- It can contain abstract and non-abstract methods
- It can contain constructors and static methods as well
- It can contain final methods which force the subclass not to change the body of the method
You cannot create an instance of an abstract class since it lacks implementation logic in its methods. You first need to create a subclass that implements all the methods before an object can be initialized.
public abstract class MyAbstractClass
{
public abstract void abstractMethod();
public void display(){ System.out.println("method"); }
}
class MyAbstractClass {
abstractMethod() {
throw new Error("This method is abstract and must be overridden");
}
display() {
console.log("method");
}
}
from abc import ABC, abstractmethod
class MyAbstractClass(ABC):
@abstractmethod
def abstractMethod(self):
pass
def display(self):
print("method")
#include <iostream>
using namespace std;
class MyAbstractClass {
public:
virtual void abstractMethod() = 0;
void display() { cout << "method" << endl; }
};
public abstract class MyAbstractClass
{
public abstract void abstractMethod();
public void display() { Console.WriteLine("method"); }
}
type MyAbstractClass interface {
abstractMethod()
display()
}
func (m concreteClass) display() {
fmt.Println("method")
}
- Using Interface An interface is a blueprint of a class that contains static constants and abstract methods. It represents the IS-A relation. You need to implement an interface to use its methods or constants.
```java
public class Main {
public static void main(String[] args) {
Car c1=new Ford();
c1.start();
Car c2=new Toyota();
c2.start();
}
}
//Creating an Interface
interface Car{ public void start(); }
//Creating classes to implement Carinterface
class Ford implements Car{
public void start() { System.out.println("Ford Car"); }
}
class Toyota implements Car{
public void start() { System.out.println("Toyota Car"); }
}
```
```javascript
class Main {
constructor() {
const c1 = new Ford();
c1.start();
const c2 = new Toyota();
c2.start();
}
}
// Creating Car class
class Car {
start() {}
}
// creating classes that extends Car class
class Ford extends Car {
start() {
console.log("Ford Car");
}
}
class Toyota extends Car {
start() {
console.log("Toyota Car");
}
}
new Main();
```
```python
class Car:
def start(self):
pass
class Ford(Car):
def start(self):
print("Ford Car")
class Toyota(Car):
def start(self):
print("Toyota Car")
if __name__ == "__main__":
c1 = Ford()
c1.start()
c2 = Toyota()
c2.start()
```
```cpp
#include <iostream>
class Car
{
public:
virtual void start() = 0; // pure virtual function
};
class Ford : public Car
{
public:
void start() { std::cout << "Ford Car\n"; }
};
class Toyota: public Car
{
public:
void start() { std::cout << "Toyota Car\n"; }
};
int main()
{
Ford c1;
c1.start();
Toyota c2;
c2.start();
return 0;
}
```
```csharp
using System;
public class Program {
static void Main(string[] args) {
Car c1 = new Ford();
c1.Start();
Car c2 = new Toyota();
c2.Start();
}
}
//Creating an Interface
public interface Car{ void Start(); }
//Creating classes to implement Car interface
public class Ford : Car{
public void Start() { Console.WriteLine("Ford Car"); }
}
public class Toyota : Car{
public void Start() { Console.WriteLine("Toyota Car"); }
}
```
```go
package main
import "fmt"
type Car interface {
Start()
}
type Ford struct {}
type Toyota struct {}
func (Ford) Start() {
fmt.Println("Ford Car")
}
func (Toyota) Start() {
fmt.Println("Toyota Car")
}
func main() {
var c1 Car = Ford {}
c1.Start()
var c2 Car = Toyota {}
c2.Start()
}
```
```java
public class Main {
public static void main(String[] args) {
Car c1=new Ford();
c1.start();
Car c2=new Toyota();
c2.start();
}
}
//Creating an Interface
interface Car{ public void start(); }
//Creating classes to implement Carinterface
class Ford implements Car{
public void start() { System.out.println("Ford Car"); }
}
class Toyota implements Car{
public void start() { System.out.println("Toyota Car"); }
}
```
```javascript
class Main {
constructor() {
const c1 = new Ford();
c1.start();
const c2 = new Toyota();
c2.start();
}
}
// Creating Car class
class Car {
start() {}
}
// creating classes that extends Car class
class Ford extends Car {
start() {
console.log("Ford Car");
}
}
class Toyota extends Car {
start() {
console.log("Toyota Car");
}
}
new Main();
```
```python
class Car:
def start(self):
pass
class Ford(Car):
def start(self):
print("Ford Car")
class Toyota(Car):
def start(self):
print("Toyota Car")
if __name__ == "__main__":
c1 = Ford()
c1.start()
c2 = Toyota()
c2.start()
```
```cpp
#include <iostream>
class Car
{
public:
virtual void start() = 0; // pure virtual function
};
class Ford : public Car
{
public:
void start() { std::cout << "Ford Car\n"; }
};
class Toyota: public Car
{
public:
void start() { std::cout << "Toyota Car\n"; }
};
int main()
{
Ford c1;
c1.start();
Toyota c2;
c2.start();
return 0;
}
```
```csharp
using System;
public class Program {
static void Main(string[] args) {
Car c1 = new Ford();
c1.Start();
Car c2 = new Toyota();
c2.Start();
}
}
//Creating an Interface
public interface Car{ void Start(); }
//Creating classes to implement Car interface
public class Ford : Car{
public void Start() { Console.WriteLine("Ford Car"); }
}
public class Toyota : Car{
public void Start() { Console.WriteLine("Toyota Car"); }
}
```
```go
package main
import "fmt"
type Car interface {
Start()
}
type Ford struct {}
type Toyota struct {}
func (Ford) Start() {
fmt.Println("Ford Car")
}
func (Toyota) Start() {
fmt.Println("Toyota Car")
}
func main() {
var c1 Car = Ford {}
c1.Start()
var c2 Car = Toyota {}
c2.Start()
}
```
Question 3
If we set the variables and attributes private, and make public methods for accessing them, we are implementing what OOP principle?
Constructors, Try-Catch, Exceptions
13 What is the difference between data abstraction and encapsulation?
Data abstraction is the ability to hide unwanted information.
The encapsulation refers to the ability to hide the data as well as the method together.
14. What are the differences between interfaces and abstract classes?
An abstract class can support both abstract and non-abstract methods. However, the interface allows only abstract methods.
In the case of an abstract class, both final and non-final variables are supported, but the interface has variables that are defined as final by default.
The abstract class can have private, and public attributes, but interfaces have attributes as public by default.
15. What is a try-catch block?
A try-catch block is used for exception handling, and the statements that may cause a potential error are enclosed in a try block. When an exception is thrown, it is caught by the catch block, where the logic to handle an exception is placed.
The try-catch blocks are usually finished by using a finally block. A ‘finally’ block is used for executing essential statements such as to free the memory, close files, or database connections, even if an exception occurs. The finally block always runs.
16. What is an exception?
An exception is a special event, which is raised during the execution of a program at runtime if there is an error during the execution. The reason for the exception is mainly due to a position in the program, where the user wants to do something for which the program is not specified, like undesirable input. The exceptions include a message with the details about the error that occurred.
Errors and exceptions are different, and an error means a problem that the program should not catch while the exception implies a condition that should be caught by the program.
In OOP there is a mechanism used for handling the exceptions raised during program execution, called exception handling. It allows for the graceful handling of undesirable results.
Question 4
Interfaces always have public attributes.
One Pager Cheat Sheet
One Pager Cheat Sheet
- You should be prepared with basic Object-Oriented programming theory when interviewing for a software engineering position.
- Object-Oriented Programming (OOP) is a programming paradigm based on objects, which contain attributes and methods, with four main principles of
inheritance,encapsulation,polymorphism, anddata abstraction, that provide advantages such as code reuse, flexibility, and improved maintainability. - Only when an
objectis created does memory consumption occur, not based on the number of attributes of the class since classes are merely a logical entity. - In object-oriented programming,
polymorphismis the ability of an object or a class to exist in multiple forms, and is realized using two types of binding, static and dynamic. - All of the listed
inheritance typesare fundamental features of Object-Oriented Programming. - Encapsulation, abstraction and method/operator overloading are important features of object-oriented programming that allow the binding of data and logic, hiding data and creating multiple methods with the same name respectively.
- Encapsulation is a key feature of Object-Oriented Programming that supports data-hiding and abstraction by making attributes
privateand usingpublic setter and getter methodsto access and modify them. - Exception handling using
try-catch blocksandfinally blockallow for the graceful handling of errors and exceptions to take place during the execution of a program. - Interfaces have
publicvisibility by default, so that any implementation class must adhere to thepublicexposed methods and attributes when implementing the interface.