As we learned earlier about polymorphism.
We discovered:
Animal* animal = new Dog();
animal->makeSound();The code works because:
Animaldefines a contact, and:
Dogimplements that contract.
This introduces one of the most important idead in software engineering:
Good sofrware depedns on contracts, not concrete implementation.
This idea is responsible for:
Modern Frameworks
Plugin Architectures
Microservices SDKs
Cloud SDKs
Database Drivers
Payment Gateways
Operating Systems
Game Engines
Enterprise SoftwareWithout contracts, software becomes:
Rigid
Tightly Coupled
Difficult To Test
Difficult To ExtendWith contracts, software becomes:
Flexible
Replaceable
Extensible
MaintainableThe Fundamental Problem
Imagine building:
Food Delivery System
You create:
class EmailService
{
public:
void sendEmail()
{
}
};Then:
class OrderService {
private:
EmailService: emailService;
};Looks fine.
Later requiremnts change:
Need SMS
Need WhatsApp
Need Push Notifications
Need Slack NotificationsNow:
OrderServiceis tightly coupled to:
EmailServiceThis is a common enterprise problem.
What Is a Contract?
A contract defines:
What must be donewithout specifying:
How it is doneExample:
Payment Gateway Contract
Must Support:
Pay()
Refund()Contract says:
WhatNot:
HowDifferent implementations:
Stripe
Razorpay
PayPal
UPIcan all satisfy the same contract.
Real-World Analogy
Consider a wall socket.
The socket defines:
Voltage
Frequency
Plug ShapeThe socket does NOT care whether the connected device is:
Laptop
Phone Charger
Television
PrinterThe socket represents:
Interface
Device represent:
ImplementationsThis is contract-based design.
What Is an Interface?
Conceptual Definition
An interface defines:
A set of operations that must be provided.
In many languages:
Java
C#
TypeScriptthere is a dedicated interface keyword.
C++ traditionally uses:
Pure Abstract Classesto implement interfaces.
First Interface Example
Class IPaymentMethod
{
public:
virtual void pay() = 0;
virtual ~IPaymentMethod() = default;
};Notice:
= 0This makes the method:
Pure VirtualMeaning:
Must be ImplementedImplementing the Interface
class CreditCardPayment :
public IPaymentMethod
{
public:
void pay() override
{
cout << "Credit Card Payment";
}
};Another implementation:
class UpiPayment :
public IPaymentMethod
{
public:
void pay() override
{
cout << "UPI Payment";
}
};Both satisfy:
IPaymentMethodcontract.
Using the Interface
void processPayment(
IPaymentMethod& payment)
{
payment.pay();
}Usage:
CreditCardPayment card;
processPayment(card);Later:
UpiPayment upi;
processPayment(upi);No code changes required.
The Power of Abstraction
Without abstraction:
void processPayment(
CreditCardPayment& payment)
{
}Only supports:
CreditCardPaymentWith abstraction:
void processPayment(
IPaymentMethod& payment)
{
}Supports:
Any Payment MethodThis dramatically improves extensibility.
What Is an Abstract Class?
An abstract class is:
A class that cannot be instantiated directly.
Example:
class Animal
{
public:
virtual void makeSound() = 0;
};Invalid:
Animal animal;Valid:
Dog dog;
Cat cat;Abstract classes exist to define common behavior.
Interface vs Abstract Class
Many beginners confuse these concepts.
Interface
Contains:
Contract OnlyExample:
class ILogger
{
public:
virtual void log() = 0;
virtual ~ILogger() = default;
};No state.
No implementation.
Purpose:
Pure ContractAbstract Class
Can contain:
State
Implementation
Abstract MethodsExample:
class Animal
{
protected:
string name;
public:
virtual void makeSound() = 0;
void sleep()
{
cout << "Sleeping";
}
};Contains:
Data
Behavior
ContractComparison Table
| Feature | Interface | Abstract Class |
|---|---|---|
| Instantiable | No | No |
| State | Usually No | Yes |
| Implementation | Usually No | Yes |
| Contract Definition | Yes | Yes |
| Shared Logic | No | Yes |
| Primary Purpose | Behavior Contract | Common Base Functionality |
UML Representation
Interface:
<<interface>>
IPaymentMethod
-----------------
pay()Implementation:
<<interface>>
IPaymentMethod
▲
|
--------------------
| |
CreditCard UpiPaymentAbstract Class:
<<abstract>>
Animal
-----------------
sleep()
makeSound()Why Interfaces Matter
Imagine:
Database LayerBad Design:
class UserService
{
private:
MySQLDatabases db;
};Problem:
Switching to:
PostgreSQL
MongoDB
SQLiterequires code changes.
Better:
class IDatabase
{
public:
virtual void save() = 0;
};Implementations:
MySQLDatabase
PostgreDatabase
MongoDatabaseNow:
UserServicedepends on:
IDatabaseinstead of:
MySQLDatabaseHuge improvement.
Programming to Abstraction
One of the most famous design principles.
Bad:
MySQLDatabase database;Better:
IDatabase& database;Bad:
CreditCardPayment payment;Better:
IPaymentMethod& payment;Rule:
Depend on what something does, not what it is.
Dependency Direction
Bad architecture:
OrderService
↓
EmailServiceOrderService depends on EmailService.
Better:
OrderService
↓
INotificationService
↑
EmailServiceNow:
EmailService
SmsService
WhatsAppServicecan all be substituted.
Extensibility Example
Requirement:
Add Slack NotificationBad Design:
Modify:
OrderServiceGood Design:
Create:
class SlackNotification
: public INotificationService
{
};Done.
No existing code changes.
This is professional design.
Testing Benefits
Interfaces dramatically improve testing.
Example:
class IEmailService
{
public:
virtual void send() = 0;
};Production:
EmailServiceTesting:
FakeEmailServiceNo real emails sent.
Testing becomes easier.
This is why interfaces dominate enterprise systems.
Common Interface Naming Convention
Common C++ style:
ILogger
IDatabase
IPaymentGateway
INotificationServicePrefix:
Iindicates interface.
Not mandatory.
But common.
Interface Segregation Preview
Bad:
class IWorker
{
public:
virtual void work() = 0;
virtual void eat() = 0;
virtual void sleep() = 0;
virtual void drive() = 0;
virtual void fly() = 0;
};Huge interface.
Many classes need only part of it.
This violates:
Interface Segregation Principle
Common Beginner Mistakes
Mistake 1
Depending on Concrete Classes
PaymentProcessor
↓
StripePaymentToo rigid.
Prefer:
PaymentProcessor
↓
IPaymentMethodMistake 2
Creating interfaces for Everything
Not every class needs an interface.
Example:
Point
Rectangle
DateUsually do not need interfaces.
Use interfaces where variation is expected.
Mistake 3
Huge Interfaces
100+ MethodsUsually poor design.
Interfaces should be focused.
Mistake 4:
Leaking Implementation Details
Bad:
class IDatabase
{
public:
virtual MySQLConnection*
getConnection() = 0;
};Now interface depends on MySQL.
Defeats abstraction.
Industry Perspective
Large-scale systems rely heavily on interfaces.
Examples:
Spring Framework
ASP.NET
Qt
Unreal Engine
AWS SDK
Azure SDK
Database Drivers
Cloud Storage SystemsWhy?
Because large systems must support:
Replacement
Testing
Evolution
ExtensionInterfaces make this possible.
Expert Notes
One of the biggest mindset shifts:
Beginner thinks:
What class should I use?Senior engineer thinks:
What contract should exist?Another insight:
Interfaces are not about implementation.
They are about boundaries.
Leave a comment
Your email address will not be published. Required fields are marked *
