Introduction to Inheritance in Java (including interfaces and abstract classes)

Imagine you’re building software for different types of vehicles: cars, trucks, and motorcycles. Each of these vehicles shares common attributes like speed, color, and fuel capacity, as well as behaviors like accelerate, brake, and refuel. Instead of writing the same code repeatedly for each type of vehicle, inheritance allows you to define these common attributes and behaviors once in a base class (or parent class). You can then create specialized versions (child classes) that extend the base class and add their own unique features.
This approach promotes code reuse (avoiding redundancy) and extensibility (easily adding new features or types).
What is Inheritance?
Inheritance is an object-oriented programming concept where one class (called the child class or subclass) can acquire the properties (fields) and behaviors (methods) of another class (called the parent class or superclass).
In Java, inheritance helps in:
Code Reusability: Avoid rewriting code by reusing functionality defined in a parent class.
Polymorphism: Treat different classes uniformly if they share a common superclass.
Extensibility: Extend existing classes to introduce new functionalities without modifying the parent class.
Syntax of Inheritance in Java
In Java, inheritance is implemented using the extends
keyword. Here's the basic syntax:
class ParentClass {
// Fields (attributes)
int speed;
// Methods (behaviors)
void displaySpeed() {
System.out.println("Speed: " + speed);
}
}
class ChildClass extends ParentClass {
// Additional fields
String model;
// Additional methods
void displayModel() {
System.out.println("Model: " + model);
}
}
Example of Inheritance in Action
// Parent class
class Vehicle {
int speed = 60;
void displaySpeed() {
System.out.println("Speed: " + speed + " km/h");
}
}
// Child class inheriting from Vehicle
class Car extends Vehicle {
String model = "Sedan";
void displayDetails() {
System.out.println("Car Model: " + model);
displaySpeed(); // Reusing method from the parent class
}
}
// Main class
public class Main {
public static void main(String[] args) {
Car myCar = new Car();
myCar.displayDetails();
}
}
Output:
Car Model: Sedan
Speed: 60 km/h
In this example, the Car
class inherits the speed
attribute and displaySpeed()
method from the Vehicle
class, demonstrating code reuse.
The Role of the super
Keyword
In Java, the super
keyword refers to the parent class (superclass) of the current object. It is used for:
Accessing parent class methods that are overridden in the child class.
Accessing parent class fields when the child class has a field with the same name.
Calling the parent class constructor to initialize fields in the parent class.
Example of super
Keyword
class Animal {
void sound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
void sound() {
super.sound(); // Calls the parent class method
System.out.println("Dog barks");
}
}
public class Main {
public static void main(String[] args) {
Dog myDog = new Dog();
myDog.sound();
}
}
Output:
Animal makes a sound
Dog barks
Key Points:
super.sound()
calls thesound()
method from theAnimal
class.This allows the child class (
Dog
) to reuse and extend the behavior of the parent class.
Types of Inheritance
Different software design problems require different approaches to inheritance. Depending on how your classes relate to one another, you might need a single direct relationship or more complex hierarchies where one class builds upon another, or multiple classes share common behavior. Understanding the different inheritance models in Java helps you choose the most effective structure for your code, promoting clarity, reuse, and maintainability.
Java supports three types of inheritance:
Single Inheritance
Multilevel Inheritance
Hierarchical Inheritance
Note: Java does not support multiple inheritance (a class inheriting from more than one class) to avoid ambiguity, but similar functionality can be achieved using interfaces.
1. Single Inheritance
In single inheritance, a class inherits from just one parent class. This is the simplest form of inheritance.
Example of Single Inheritance
// Parent class
class Animal {
void eat() {
System.out.println("This animal can eat");
}
}
// Child class inheriting from Animal
class Dog extends Animal {
void bark() {
System.out.println("The dog barks");
}
}
// Main class
public class Main {
public static void main(String[] args) {
Dog myDog = new Dog();
myDog.eat(); // Inherited method
myDog.bark(); // Method specific to Dog
}
}
Output:
This animal can eat
The dog barks
Explanation:
Dog
inherits theeat()
method fromAnimal
and defines its own methodbark()
.
2. Multilevel Inheritance
In multilevel inheritance, a class inherits from a child class, making it a grandchild class. This forms a chain of inheritance.
Example of Multilevel Inheritance
// Grandparent class
class Animal {
void eat() {
System.out.println("This animal can eat");
}
}
// Parent class inheriting from Animal
class Dog extends Animal {
void bark() {
System.out.println("The dog barks");
}
}
// Child class inheriting from Dog
class Puppy extends Dog {
void weep() {
System.out.println("The puppy weeps");
}
}
// Main class
public class Main {
public static void main(String[] args) {
Puppy myPuppy = new Puppy();
myPuppy.eat(); // Inherited from Animal
myPuppy.bark(); // Inherited from Dog
myPuppy.weep(); // Method specific to Puppy
}
}
Output:
This animal can eat
The dog barks
The puppy weeps
Explanation:
Puppy
inherits methods from bothDog
andAnimal
classes, forming a chain of inheritance.
3. Hierarchical Inheritance
In hierarchical inheritance, multiple child classes inherit from the same parent class.
Example of Hierarchical Inheritance
// Parent class
class Animal {
void eat() {
System.out.println("This animal can eat");
}
}
// Child class 1
class Dog extends Animal {
void bark() {
System.out.println("The dog barks");
}
}
// Child class 2
class Cat extends Animal {
void meow() {
System.out.println("The cat meows");
}
}
// Main class
public class Main {
public static void main(String[] args) {
Dog myDog = new Dog();
Cat myCat = new Cat();
myDog.eat(); // Inherited from Animal
myDog.bark(); // Dog-specific method
myCat.eat(); // Inherited from Animal
myCat.meow(); // Cat-specific method
}
}
Output:
This animal can eat
The dog barks
This animal can eat
The cat meows
Explanation:
- Both
Dog
andCat
inherit theeat()
method from theAnimal
class, but each has its own behavior (bark()
forDog
,meow()
forCat
).
Method Overriding
Imagine you are designing a software system with a parent class Animal
that has a method sound()
to represent the sound an animal makes. If you create a child class Dog
, you would want the sound()
method to produce a dog-specific sound (like barking). Instead of modifying the sound()
method in the parent class (which would affect all other child classes), you can redefine it in the Dog
class. This is known as method overriding.
Method overriding allows you to:
Customize behavior of inherited methods for specific subclasses.
Enable runtime polymorphism where the appropriate method is called based on the actual object type.
Enhance code flexibility and maintainability without altering the parent class.
What is Method Overriding?
Method overriding occurs when a child class provides a specific implementation of a method that is already defined in its parent class. The method in the child class must have:
The same name as the method in the parent class.
The same parameters (number and type).
The same return type (or a subtype).
Rules of Method Overriding
Same Method Signature: The overriding method must have the same name, return type, and parameters as the method in the parent class.
Inheritance Requirement: Method overriding requires a parent-child relationship (inheritance).
Access Modifier: The overriding method cannot have a more restrictive access modifier than the method in the parent class:
If the parent method is
public
, the overriding method must also bepublic
.If the parent method is
protected
, the overriding method can beprotected
orpublic
.
Static Methods: Static methods cannot be overridden (they can only be hidden by static methods in child classes).
Final Methods: Methods declared as
final
in the parent class cannot be overridden.Private Methods: Private methods are not visible to child classes and thus cannot be overridden.
Constructor Rules: Constructors cannot be overridden.
The Significance of the @Override
Annotation
The @Override
annotation is used to indicate that a method is intended to override a method in the parent class. It has several benefits:
Compile-Time Checking: If the method signature does not match any method in the parent class, the compiler will generate an error.
Code Clarity: It makes the code more readable and clearly indicates the developer's intent to override a method.
Reduces Bugs: Helps catch mistakes, such as typos in the method name or incorrect parameters, which might otherwise lead to subtle bugs.
Example of @Override
in Action
// Parent class
class Animal {
void sound() {
System.out.println("Some generic animal sound");
}
}
// Child class overriding the sound method
class Dog extends Animal {
@Override
void sound() {
System.out.println("The dog barks");
}
}
// Main class
public class Main {
public static void main(String[] args) {
Animal myAnimal = new Animal();
Animal myDog = new Dog();
myAnimal.sound(); // Calls the parent class method
myDog.sound(); // Calls the overridden method in the Dog class
}
}
Output:
Some generic animal sound
The dog barks
Explanation of the Example
Parent Class (
Animal
):- Contains a
sound()
method with generic behavior.
- Contains a
Child Class (
Dog
):Overrides the
sound()
method to provide dog-specific behavior.The
@Override
annotation ensures that the compiler checks for correctness.
Main Class:
- Demonstrates runtime polymorphism. Even though
myDog
is declared as typeAnimal
, it calls the overridden method in theDog
class because its actual object is aDog
.
- Demonstrates runtime polymorphism. Even though
Runtime Polymorphism (Dynamic Method Dispatch)
In software development, flexibility and maintainability are essential for building scalable and adaptable applications. Imagine a scenario where you have a class hierarchy with different types of shapes like Circle
, Rectangle
, and Triangle
. You want to write code that processes these shapes uniformly without knowing their specific types. Polymorphism allows you to achieve this by enabling a single interface (e.g., a parent class Shape
) to represent multiple types of objects (e.g., Circle
, Rectangle
, Triangle
).
Runtime polymorphism, also known as dynamic method dispatch, allows method calls to be resolved at runtime rather than compile time. This means that the appropriate method implementation is chosen based on the actual object being referenced, not the reference type. This flexibility allows for cleaner, more maintainable, and extensible code.
Explanation of Dynamic Method Dispatch
Dynamic method dispatch is a mechanism by which a call to an overridden method is resolved at runtime. It works as follows:
When a method in a child class overrides a method in a parent class, the overridden method is invoked based on the actual type of the object (the runtime type), even if the reference is of the parent class type.
This allows the same reference type to call different method implementations depending on the actual object it refers to.
Key Points:
The reference type determines what methods can be called.
The object type (the actual instance) determines which version of the method is executed.
How Method Calls are Resolved at Runtime
Compile Time: The compiler checks whether the method exists in the reference type (usually the parent class).
Runtime: The JVM determines the actual object type and calls the appropriate overridden method.
Code Example: Demonstrating Runtime Polymorphism
Let's illustrate dynamic method dispatch with an example involving animals making different sounds.
// Parent class
class Animal {
void sound() {
System.out.println("Some generic animal sound");
}
}
// Child class 1
class Dog extends Animal {
@Override
void sound() {
System.out.println("The dog barks");
}
}
// Child class 2
class Cat extends Animal {
@Override
void sound() {
System.out.println("The cat meows");
}
}
// Main class
public class Main {
public static void main(String[] args) {
// Parent class reference, different child class objects
Animal myAnimal;
myAnimal = new Dog();
myAnimal.sound(); // Output: The dog barks
myAnimal = new Cat();
myAnimal.sound(); // Output: The cat meows
}
}
Output:
The dog barks
The cat meows
Explanation of the Example
Parent Class (
Animal
):- Defines a generic
sound()
method.
- Defines a generic
Child Classes (
Dog
andCat
):- Each class overrides the
sound()
method to provide specific behavior.
- Each class overrides the
Main Class:
The reference
myAnimal
is of typeAnimal
, but it is assigned different child class objects (Dog
andCat
).Dynamic Method Dispatch ensures that the correct overridden method (
Dog
'ssound()
orCat
'ssound()
) is called based on the actual object type at runtime.
Benefits of Runtime Polymorphism
Flexibility: Code can work with different types of objects through a common interface.
Maintainability: Adding new subclasses doesn't require changing existing code.
Extensibility: New behaviors can be introduced by creating new subclasses without modifying existing logic.
Example of Flexibility
Imagine processing a list of different animal types:
public class Main {
public static void main(String[] args) {
Animal[] animals = { new Dog(), new Cat(), new Animal() };
for (Animal animal : animals) {
animal.sound(); // Each object calls its specific sound() method
}
}
}
Output:
The dog barks
The cat meows
Some generic animal sound
Abstract Classes
In software development, we often encounter situations where we need to model a general concept while leaving some details to be specified by more specialized classes. For example, consider the concept of a Shape: all shapes have common characteristics, such as a method to calculate the area, but the implementation of calculating the area differs for different shapes like circles, rectangles, and triangles.
Abstract classes provide a way to define a blueprint for a group of related classes. They allow you to declare methods that must be implemented by any class that extends the abstract class, enforcing a consistent design while allowing flexibility in the specific implementations.
Use abstract classes when:
You want to provide a common base class with some shared behavior but allow subclasses to provide specific implementations.
You want to enforce that certain methods must be implemented by subclasses.
You need to include both defined methods (with bodies) and undefined methods (abstract methods) in the base class.
Defining Abstract Classes and Abstract Methods
What is an Abstract Class?
An abstract class is a class that cannot be instantiated on its own. It can contain:
Abstract Methods: Methods without a body (implementation), which must be implemented by subclasses.
Concrete Methods: Methods with a body that provide default behavior.
An abstract class is declared using the abstract
keyword:
abstract class ClassName {
abstract void abstractMethod(); // Abstract method (no body)
void concreteMethod() { // Concrete method (has a body)
System.out.println("This is a concrete method.");
}
}
What is an Abstract Method?
An abstract method is a method declared in an abstract class without a body. Subclasses that extend the abstract class must provide an implementation for the abstract method:
abstract void abstractMethod(); // No implementation
Differences Between Abstract Classes and Concrete Classes
Feature | Abstract Class | Concrete Class |
Instantiation | Cannot be instantiated directly. | Can be instantiated directly. |
Abstract Methods | Can contain abstract methods (methods without a body). | Cannot contain abstract methods. |
Concrete Methods | Can contain concrete methods (methods with a body). | Only contains concrete methods. |
Usage | Used to define a common blueprint for subclasses. | Used for creating fully-defined objects. |
Code Example: Using an Abstract Class to Model Real-World Scenarios
Let's model different types of shapes using an abstract class Shape
that defines a method to calculate the area. Subclasses Circle
and Rectangle
will provide specific implementations of the calculateArea()
method.
// Abstract class
abstract class Shape {
// Abstract method
abstract double calculateArea();
// Concrete method
void displayShape() {
System.out.println("This is a shape.");
}
}
// Subclass 1: Circle
class Circle extends Shape {
double radius;
Circle(double radius) {
this.radius = radius;
}
@Override
double calculateArea() {
return Math.PI * radius * radius;
}
}
// Subclass 2: Rectangle
class Rectangle extends Shape {
double length;
double width;
Rectangle(double length, double width) {
this.length = length;
this.width = width;
}
@Override
double calculateArea() {
return length * width;
}
}
// Main class
public class Main {
public static void main(String[] args) {
Shape circle = new Circle(5.0);
Shape rectangle = new Rectangle(4.0, 6.0);
circle.displayShape();
System.out.println("Circle Area: " + circle.calculateArea());
rectangle.displayShape();
System.out.println("Rectangle Area: " + rectangle.calculateArea());
}
}
Output:
This is a shape.
Circle Area: 78.53981633974483
This is a shape.
Rectangle Area: 24.0
Explanation of the Code
Abstract Class (
Shape
):Defines an abstract method
calculateArea()
that must be implemented by any subclass.Contains a concrete method
displayShape()
.
Subclasses (
Circle
andRectangle
):Provide specific implementations of the
calculateArea()
method.Each subclass has fields specific to its shape (e.g.,
radius
forCircle
andlength
/width
forRectangle
).
Main Class:
Demonstrates polymorphism by referencing
Shape
and calling methods on different shape objects.The
displayShape()
method is reused for both shapes, whilecalculateArea()
is customized for each type.
When to Use Abstract Classes
When you have a common concept (e.g.,
Shape
,Animal
) with shared behavior that needs to be partially implemented.When you want to enforce a contract (certain methods must be implemented) but also provide some default behavior.
When you need to work with hierarchies of related classes.
Interfaces
Java supports single inheritance of classes to avoid ambiguity. However, real-world design problems often require a class to inherit behavior from multiple sources. For example, a RobotDog
might need the behaviors of both a Dog
and a Machine
. This is where interfaces come into play.
Interfaces provide a mechanism for achieving multiple inheritance in Java. They allow a class to inherit behavior from multiple sources while maintaining design flexibility. Additionally, interfaces help in defining contracts that classes must follow, ensuring consistency across different implementations.
Defining and Implementing Interfaces
An interface in Java is a collection of abstract methods and constants. Interfaces cannot contain method bodies (except default and static methods). A class implements an interface using the implements
keyword and must provide implementations for all the abstract methods declared in the interface.
Defining an Interface
interface Animal {
// Abstract method (no implementation)
void sound();
// Constant (public, static, and final by default)
int LEGS = 4; // Equivalent to: public static final int LEGS = 4;
}
Implementing an Interface
class Dog implements Animal {
@Override
public void sound() {
System.out.println("The dog barks");
}
}
Differences Between Interfaces and Abstract Classes
Feature | Interface | Abstract Class |
Instantiation | Cannot be instantiated. | Cannot be instantiated. |
Method Types | Only abstract methods (default and static methods allowed). | Can have abstract and concrete methods. |
Fields | Only constants (public static final ). | Can have instance variables and constants. |
Inheritance | A class can implement multiple interfaces. | A class can extend only one abstract class. |
Access Modifiers | Methods are public by default. | Can have any access modifier. |
Use Case | Used for defining a contract (behavior). | Used for defining a blueprint with partial behavior. |
Example: Implementing Multiple Interfaces
In this example, a RobotDog
class implements both Animal
and Machine
interfaces, demonstrating multiple inheritance.
// First interface
interface Animal {
void sound();
int LEGS = 4; // Constant
}
// Second interface
interface Machine {
void recharge();
}
// Class implementing both interfaces
class RobotDog implements Animal, Machine {
@Override
public void sound() {
System.out.println("The robot dog makes a mechanical bark");
}
@Override
public void recharge() {
System.out.println("Recharging robot dog");
}
void displayLegs() {
System.out.println("Robot dog has " + LEGS + " legs");
}
}
// Main class
public class Main {
public static void main(String[] args) {
RobotDog myRobotDog = new RobotDog();
myRobotDog.sound();
myRobotDog.recharge();
myRobotDog.displayLegs();
}
}
Output:
The robot dog makes a mechanical bark
Recharging robot dog
Robot dog has 4 legs
Explanation:
The
RobotDog
class implements two interfaces,Animal
andMachine
.It provides implementations for the
sound()
andrecharge()
methods.The constant
LEGS
is accessed from theAnimal
interface.
Reference Type and Method Execution
In Java, a reference type can be:
An Interface
An Abstract Class
A Parent Class
The reference type dictates what methods can be called (methods available in the reference type). However, the actual method executed is determined by the type of object (the instance created on the right side with new
).
Example Demonstrating Different Reference Types
interface Animal {
void sound();
}
abstract class Pet {
abstract void sleep();
}
class Dog extends Pet implements Animal {
@Override
public void sound() {
System.out.println("Dog barks");
}
@Override
void sleep() {
System.out.println("Dog sleeps");
}
void wagTail() {
System.out.println("Dog wags tail");
}
}
public class Main {
public static void main(String[] args) {
// Reference type is Animal (Interface)
Animal myAnimal = new Dog();
myAnimal.sound(); // Allowed by Animal interface
// myAnimal.sleep(); // Not allowed (sleep() not in Animal)
// Reference type is Pet (Abstract Class)
Pet myPet = new Dog();
myPet.sleep(); // Allowed by Pet abstract class
// myPet.sound(); // Not allowed (sound() not in Pet)
// Reference type is Dog (Concrete Class)
Dog myDog = new Dog();
myDog.sound(); // Allowed
myDog.sleep(); // Allowed
myDog.wagTail(); // Allowed
}
}
Output:
Dog barks
Dog sleeps
Dog barks
Dog sleeps
Dog wags tail
Explanation:
Animal myAnimal = new Dog();
:The reference type
Animal
allows calling thesound()
method defined in theAnimal
interface.The actual method that runs is
Dog
'ssound()
.
Pet myPet = new Dog();
:The reference type
Pet
allows calling thesleep()
method defined in thePet
abstract class.The actual method that runs is
Dog
'ssleep()
.
Dog myDog = new Dog();
:- The reference type
Dog
allows calling all methods specific toDog
.
- The reference type
Interfaces and Constants
Interfaces can contain constants, which are implicitly public
, static
, and final
. These constants are accessible via the interface name and cannot be changed once assigned.
Example with Constants in an Interface
interface GameSettings {
int MAX_PLAYERS = 4; // public static final by default
String GAME_NAME = "Chess"; // public static final by default
}
class ChessGame implements GameSettings {
void displaySettings() {
System.out.println("Game: " + GAME_NAME);
System.out.println("Max Players: " + MAX_PLAYERS);
}
}
public class Main {
public static void main(String[] args) {
ChessGame game = new ChessGame();
game.displaySettings();
}
}
Output:
Game: Chess
Max Players: 4
Explanation:
The constants
MAX_PLAYERS
andGAME_NAME
are defined in theGameSettings
interface.They are accessed in the
ChessGame
class without needing to redefine them.
In Java, if a public abstract class or a public interface is declared, the source file must be named after that class or interface, with the .java
extension. This rule is the same as for regular public classes. For example, if you declare public abstract class Animal
or public interface Animal
, the file must be named Animal.java
. If multiple classes or interfaces are declared in the same file, only one of them can be public, and the filename must match the public class or interface name.
Implicit Constructor Chaining in Inheritance
When a subclass is instantiated, Java automatically ensures that all constructors in the inheritance hierarchy are called from the top down (parent to child). This is called constructor chaining.
How it works:
The subclass constructor implicitly calls the default constructor (
super()
) of its immediate parent.This process repeats up the inheritance chain until the
Object
class constructor is reached.Only then does the subclass constructor execute its own logic.
Example:
class Animal {
public Animal() {
System.out.println("Animal constructor: Default");
}
}
class Dog extends Animal {
public Dog() {
// Implicit super() call to Animal's default constructor
System.out.println("Dog constructor: Default");
}
}
class GermanShepherd extends Dog {
public GermanShepherd() {
// Implicit super() call to Dog's default constructor
System.out.println("GermanShepherd constructor: Default");
}
}
public class Main {
public static void main(String[] args) {
new GermanShepherd();
}
}
Output:
Animal constructor: Default
Dog constructor: Default
GermanShepherd constructor: Default
Key Points:
Works automatically when no explicit
super
is usedRequires parent classes to have default constructors
Execution order: Root ancestor → ... → Immediate parent → Current class
Explicit Constructor Chaining with super
When you need to call specific parent constructors (especially parameterized ones), use the super
keyword explicitly.
Rules:
Must be the first statement in the subclass constructor
Can call any overloaded parent constructor
Required when parent lacks a default constructor
Example:
class Vehicle {
private String make;
private String model;
public Vehicle(String make) {
this.make = make;
System.out.println("Vehicle constructor: Make only");
}
public Vehicle(String make, String model) {
this.make = make;
this.model = model;
System.out.println("Vehicle constructor: Make & Model");
}
}
class Car extends Vehicle {
private int year;
public Car(String make, String model, int year) {
// Explicitly choose the two-parameter parent constructor
super(make, model);
this.year = year;
System.out.println("Car constructor: Three parameters");
}
public Car(String make, int year) {
// Chain to sibling constructor using this()
this(make, "Unknown Model", year);
}
}
public class Main {
public static void main(String[] args) {
Car sedan = new Car("Toyota", "Camry", 2023);
System.out.println("\n");
Car suv = new Car("Ford", 2022);
}
}
Output:
Vehicle constructor: Make & Model
Car constructor: Three parameters
Vehicle constructor: Make & Model
Car constructor: Three parameters
Key Points:
super(make, model)
explicitly callsVehicle
's two-parameter constructorThe
this()
in the secondCar
constructor demonstrates constructor chaining within the same classMixing
super()
andthis()
in the same constructor is illegal - only one can be first
Subscribe to my newsletter
Read articles from Jyotiprakash Mishra directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Jyotiprakash Mishra
Jyotiprakash Mishra
I am Jyotiprakash, a deeply driven computer systems engineer, software developer, teacher, and philosopher. With a decade of professional experience, I have contributed to various cutting-edge software products in network security, mobile apps, and healthcare software at renowned companies like Oracle, Yahoo, and Epic. My academic journey has taken me to prestigious institutions such as the University of Wisconsin-Madison and BITS Pilani in India, where I consistently ranked among the top of my class. At my core, I am a computer enthusiast with a profound interest in understanding the intricacies of computer programming. My skills are not limited to application programming in Java; I have also delved deeply into computer hardware, learning about various architectures, low-level assembly programming, Linux kernel implementation, and writing device drivers. The contributions of Linus Torvalds, Ken Thompson, and Dennis Ritchie—who revolutionized the computer industry—inspire me. I believe that real contributions to computer science are made by mastering all levels of abstraction and understanding systems inside out. In addition to my professional pursuits, I am passionate about teaching and sharing knowledge. I have spent two years as a teaching assistant at UW Madison, where I taught complex concepts in operating systems, computer graphics, and data structures to both graduate and undergraduate students. Currently, I am an assistant professor at KIIT, Bhubaneswar, where I continue to teach computer science to undergraduate and graduate students. I am also working on writing a few free books on systems programming, as I believe in freely sharing knowledge to empower others.