OOP Concepts · Polymorphism in Depth

Abstract Classes

An abstract class is a partly built blueprint. It holds everything a family of classes has in common and leaves blanks each child must fill in. You can never build the blueprint itself.

Beginner 6 min Lesson 16 of 38 Runnable examplesExamples use modern JavaScript (ES2022 private fields) and C# 13.
0/38 in OOP Concepts
On this page · 6 min · Beginner

In simple words#

An abstract class is a half-built flat: walls and wiring are done (shared code), but each owner must finish the interiors (abstract methods). Nobody can live in the half-built version.

abstract class
Cannot be instantiated.
Shared code
Common methods written once.
Abstract member
Must be implemented by children.

Learning objectives#

  • Explain what makes a class abstract
  • Share fields and methods in an abstract base
  • Force subclasses to implement abstract members
  • Recognise when an abstract class fits

Explanation#

An abstract class cannot be instantiated: there is no such thing as “just an Employee” — only salaried, hourly or contract employees.

It can contain constructors, fields, normal methods and abstract methods. That mix is what makes it useful: shared code plus required blanks.

Subclasses inherit the shared parts and must implement every abstract method. In C#, forgetting one is a compile error.

An abstract class fits when the classes are truly related (“is-a”), share state or code, and you want to control the overall workflow.

JavaScript has no abstract keyword; use the new.target check and throwing methods shown below. TypeScript and C# support abstract directly.

Syntax#

C# Illustrative
public abstract class Employee(string name)
{
    public string Name => name;
    public abstract decimal CalculatePay();             // each type decides
    public string Payslip() => 
quot;
{Name}: {CalculatePay()}"; // shared
} public class HourlyEmployee(string name, decimal rate, int hours) : Employee(name) { public override decimal CalculatePay() => rate * hours; }

Code example: One payroll, three kinds of staff#

JavaScriptOne payroll, three kinds of staff Runnable
class Employee {
  constructor(name) {
    if (new.target === Employee) throw new TypeError('Cannot create an abstract Employee');
    this.name = name;
  }
  calculatePay() {                                  // abstract
    throw new Error('calculatePay() not implemented');
  }
  payslip() {                                       // shared
    return `${this.name}: ₹${this.calculatePay()}`;
  }
}


class SalariedEmployee extends Employee {
  constructor(name, monthly) { super(name); this.monthly = monthly; }
  calculatePay() { return this.monthly; }
}


class HourlyEmployee extends Employee {
  constructor(name, rate, hours) { super(name); this.rate = rate; this.hours = hours; }
  calculatePay() { return this.rate * this.hours; }
}


class Contractor extends Employee {
  constructor(name, invoices) { super(name); this.invoices = invoices; }
  calculatePay() { return this.invoices.reduce((sum, a) => sum + a, 0); }
}


const staff = [
  new SalariedEmployee('Asha', 60000),
  new HourlyEmployee('Ravi', 500, 80),
  new Contractor('Meera', [15000, 22000]),
];


staff.forEach(e => console.log(e.payslip()));
const total = staff.reduce((sum, e) => sum + e.calculatePay(), 0);
console.log('Payroll total:', total);


try { new Employee('Ghost'); } catch (e) { console.log(e.message); }
Expected output
Asha: ₹60000
Ravi: ₹40000
Meera: ₹37000
Payroll total: 137000
Cannot create an abstract Employee
Opens this example in the full playground

Step-by-step explanation#

  1. Employee holds what every employee has: a name and the payslip format.
  2. calculatePay is abstract: each subclass calculates pay its own way.
  3. payslip() is written once and works for all three types because it calls this.calculatePay().
  4. The payroll code only deals with “an Employee” — it never checks which kind.
  5. Creating a plain Employee is blocked.

Real-world use case#

A document-export feature has an abstract Exporter with Export() that loads the data, calls the abstract Render() and saves the file. PdfExporter and CsvExporter only write Render().

Common mistakes#

Abstract class with only abstract members

If there is no shared code or state, use an interface — it is lighter and a class can implement several.

Using an abstract class for unrelated types

A Car and an Invoice both being “Printable” is a capability, not an is-a relationship. That is an interface.

Huge abstract base classes

A base with 30 members forces every child to carry them all. Keep the base small.

Best practices#

  • Put shared state and workflow in the abstract class
  • Keep abstract members few and clearly named
  • Use abstract classes for closely related types only
  • Combine with interfaces for capabilities

Remember this#

Abstract class = shared code + required blanks.

Cannot use new on it — only on its children.

Related types sharing code → abstract class.

Practice exercise#

Your task: Create an abstract Account class with a balance and an abstract interestRate(). Create SavingsAccount (4%) and FixedDeposit (7%), and a shared method yearlyInterest() = balance × rate / 100.

Need a hint?
yearlyInterest lives in Account and calls this.interestRate().
Show solution
JavaScript Runnable
class Account {
  constructor(balance) {
    if (new.target === Account) throw new Error('Account is abstract');
    this.balance = balance;
  }
  interestRate() { throw new Error('not implemented'); }
  yearlyInterest() { return (this.balance * this.interestRate()) / 100; }
}
class SavingsAccount extends Account { interestRate() { return 4; } }
class FixedDeposit extends Account { interestRate() { return 7; } }
console.log(new SavingsAccount(10000).yearlyInterest()); // 400
console.log(new FixedDeposit(10000).yearlyInterest());   // 700
Opens this example in the full playground

Mini quiz#

Abstract Classes quizTrue or false Question 1 of 3

An abstract class can have a constructor.

Score so far: 0/0

Want more? Practise all OOP Concepts MCQs · OOP Concepts interview questions

My notes#

Saved in this browser.

Progress is saved in this browser. Sign in to sync.