OOP Concepts Tutorial
Classes, objects, the four pillars, SOLID and design patterns — explained with JavaScript and C# side by side.
- Topics
- 38
- Full lessons
- 38
- Est. hours
- ~7
- Interview Qs
- 29
Overview
Object-oriented programming (OOP) organises code around objects: bundles of data (state) and the behaviour that works on that data. Most languages you will use professionally — C#, Java, TypeScript, JavaScript, Python — support it.
This track teaches the concepts once, language-neutrally, then shows them in JavaScript (runnable right here) and C#. It ends with SOLID principles and the design patterns interviewers ask about most.
What you will learn
- Model real-world problems with classes and objects
- Apply encapsulation, abstraction, inheritance and polymorphism
- Choose between abstract classes, interfaces and composition
- Write maintainable code with SOLID and common design patterns
Prerequisites
None — this track starts from the very beginning.
Learning path
The recommended sequence, from beginner to advanced. Each stage builds on the one before.
- 1Foundations · 8 topics · BeginnerIntroduction to OOP · Procedural vs Object-Oriented · Classes and Objects · Constructors · Fields, Properties and Methods · Access Modifiers · Static Members · The this Keyword
- 2The Four Pillars · 4 topics · BeginnerEncapsulation · Abstraction · Inheritance · Polymorphism
- 3Polymorphism in Depth · 6 topics · Beginner → IntermediateMethod Overloading · Method Overriding · Virtual and Abstract Methods · Abstract Classes · Interfaces · Abstract Class vs Interface
- 4Object Relationships · 3 topics · IntermediateAssociation, Aggregation and Composition · Composition over Inheritance · Dependency Injection Basics
- 5Design Principles · 6 topics · IntermediateSOLID Principles · Single Responsibility Principle · Open/Closed Principle · Liskov Substitution Principle · Interface Segregation Principle · Dependency Inversion Principle
- 6Design Patterns · 6 topics · Intermediate → AdvancedDesign Patterns Overview · Singleton Pattern · Factory Pattern · Strategy Pattern · Observer Pattern · Repository Pattern
- 7Practice · 5 topics · AdvancedOOP in JavaScript · OOP in C# · UML Class Diagrams · OOP Practice Project · OOP Interview Questions
Complete topic list
38 topicsFoundations
8 topics- Introduction to OOPBeginner6m
- Procedural vs Object-OrientedBeginner5m
- Classes and ObjectsBeginner5m
- ConstructorsBeginner6m
- Fields, Properties and MethodsBeginner5m
- Access ModifiersBeginner5m
- Static MembersBeginner5m
- The this KeywordBeginner5m
The Four Pillars
4 topics- EncapsulationBeginner5m
- AbstractionBeginner6m
- InheritanceBeginner5m
- PolymorphismBeginner5m
Polymorphism in Depth
6 topics- Method OverloadingBeginner5m
- Method OverridingBeginner5m
- Virtual and Abstract MethodsBeginner6m
- Abstract ClassesBeginner6m
- InterfacesBeginner5m
- Abstract Class vs InterfaceIntermediate6m
Object Relationships
3 topics- Association, Aggregation and CompositionIntermediate6m
- Composition over InheritanceIntermediate6m
- Dependency Injection BasicsIntermediate5m
Design Principles
6 topics- SOLID PrinciplesIntermediate6m
- Single Responsibility PrincipleIntermediate5m
- Open/Closed PrincipleIntermediate5m
- Liskov Substitution PrincipleIntermediate6m
- Interface Segregation PrincipleIntermediate5m
- Dependency Inversion PrincipleIntermediate5m
Design Patterns
6 topics- Design Patterns OverviewIntermediate6m
- Singleton PatternIntermediate5m
- Factory PatternIntermediate5m
- Strategy PatternAdvanced5m
- Observer PatternAdvanced5m
- Repository PatternAdvanced5m
Practice
5 topics- OOP in JavaScriptAdvanced6m
- OOP in C#Advanced6m
- UML Class DiagramsAdvanced5m
- OOP Practice ProjectAdvanced7m
- OOP Interview QuestionsAdvanced15m
Visual guides
2 diagramsCode example
A taste of the track, from Introduction to OOP.
class Book {
constructor(title, author) {
this.title = title; // state
this.author = author;
this.isBorrowed = false;
}
borrow() { // behaviour
if (this.isBorrowed) return `${this.title} is already borrowed`;
this.isBorrowed = true;
return `You borrowed ${this.title}`;
}
}
const book1 = new Book('Wings of Fire', 'A. P. J. Abdul Kalam');
const book2 = new Book('The Guide', 'R. K. Narayan');
console.log(book1.borrow());
console.log(book1.borrow());
console.log(book2.isBorrowed);
console.log(book1);
You borrowed Wings of Fire
Wings of Fire is already borrowed
false
{ title: 'Wings of Fire', author: 'A. P. J. Abdul Kalam', isBorrowed: true }Practice exercises
Model a LightBulb with a state isOn and two methods: toggle() (switches state) and status() (returns "ON" or "OFF"). Toggle it twice and log the status each time.
Rewrite this procedural code as a Counter class with a private count that can never go below 0: let count = 0; function decrement() { count--; }
Create a Rectangle class with width and height, and two methods: area() and perimeter(). Create two rectangles and log their areas.
Create a User class whose constructor takes email and role (default "viewer"). Throw an error if the email has no "@". Create one valid user and catch the error for an invalid one.
Create a Rectangle class with width and height fields, a computed area getter, and a setter for width that rejects values ≤ 0.
Create a PasswordVault class that stores passwords in a private #store Map. Expose save(site, password) and has(site), but no way to read a password back.
Show all 37 exercises
Create a Temperature class with a static method fromFahrenheit(f) that returns a new Temperature in Celsius, and a static constant FREEZING = 0.
Create a QueryBuilder class with where(field), orderBy(field) and build() methods. where and orderBy store their values and return this, so you can write new QueryBuilder().where("age").orderBy("name").build().
Create a Temperature class with a private #celsius field. Add a celsius getter, a celsius setter that rejects values below -273.15, and a fahrenheit getter.
Write a TypeScript interface Shape with area(): number, and two classes Circle and Rectangle that implement it. Write a function totalArea(shapes: Shape[]).
Create a Shape base class with a name and an area() method returning 0. Create Circle and Square subclasses that override area(). Log the area of each.
Create Notification classes — Email, Sms and Push — each with a send(message) method that returns a different string. Send the same message through all three in a loop.
Write a JavaScript function area(a, b) that returns the area of a square when called with one number and of a rectangle when called with two.
Create a Shape class with describe() returning "A shape", and a Circle subclass whose describe() returns the parent text plus " that is round". Use super.
Create a base class Animal with a "virtual" describe() that returns "<name> is an animal" and an "abstract" sound() that throws. Create Dog with sound() returning "Woof", then log both methods.
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.
Define a Logger “interface” with one method log(message). Implement ConsoleLogger (returns "console: msg") and MemoryLogger (stores messages in an array). Write a function process(logger) that logs "started" and works with both.
Model a Bird (abstract class with name and a shared describe()) and a Flyer capability (fly()). Create Sparrow (bird + flyer), Penguin (bird only) and Drone (flyer only, not a bird). Log which of the three can fly.
Create a Playlist that aggregates Song objects (songs exist independently) and a Song that is composed of a private Lyrics object it creates itself. Log the playlist length and the first line of a song’s lyrics.
Build a Character that has a weapon part. Create Sword (attack returns "slashes for 10") and Bow (attack returns "shoots for 7"). Make a character, attack, switch weapon, attack again.
Write a Greeter class that receives a clock object with a getHour() method. greet() returns "Good morning" before 12 and "Good afternoon" otherwise. Test it with two fake clocks.
Identify which SOLID principle each smell violates: (1) a PaymentProcessor with a switch on payment type that grows every month; (2) an IWorker interface with Work() and Eat() that robots must implement; (3) a ReportService that creates new SqlConnection() inside its methods.
This class does two jobs: class Report { constructor(data) { this.data = data; } average() { ... } toCsv() { ... } }. Split it into Report (average) and ReportCsvFormatter (toCsv), then use both.
Make shipping cost extensible: create StandardShipping (₹50) and ExpressShipping (₹150), each with cost(). Write a function orderTotal(amount, shipping) that never needs editing when a new shipping type appears. Then add FreeShipping.
Bird has fly(). Penguin extends Bird and throws in fly() — an LSP violation. Redesign with a Bird base (eat()) and a separate FlyingBird subclass (fly()), so Penguin never promises to fly.
A Worker contract has work() and eat(). A Robot can work but not eat. Split it into Workable and Eatable roles, implement Human (both) and Robot (work only), and run a shift that calls work() on everyone who can work.
Write a PriceService that depends on a rateProvider with getRate(currency). It converts an INR amount into another currency. Use a FixedRateProvider ({ USD: 0.012 }) for a quick test.
Write a tiny Decorator (structural pattern): a function withTimestamp(logger) that returns a new logger whose log(msg) adds "2026-10-28 " in front of the original logger’s output.
Create a Logger singleton with a static getInstance() method and a log(msg) method that stores messages in an array. Log from two “different places” and show both messages are in the same logger.
Create a ShapeFactory.create(type, size) that returns a Circle or Square object with an area() method. Create one of each and log their areas (round the circle to 2 decimals).
Create a TextFormatter that uses a strategy to format a string: UpperCaseStrategy, LowerCaseStrategy and TitleCaseStrategy. Format "hello oop world" with each.
Create a NewsChannel subject with subscribe(fn) and publish(headline). Subscribe two readers that log "Asha read: …" and "Ravi read: …", publish one headline, unsubscribe Ravi, and publish another.
Write a UserRepository (in memory) with add(user), findByEmail(email) and count(). Add two users and look one up by email, ignoring case.
Write a Serializable mixin that adds toJSONString() (returns JSON.stringify(this)) to any class. Apply it to a Product class with name and price and log the result.
Add a FixedDepositAccount (sealed) that never allows withdrawals and pays 7% interest via IInterestBearing. Create one with 10000, try to withdraw 100 and print the interest.
Write a Mermaid class diagram for: a Library has many Books (books can exist without the library); a Member borrows 0..5 Books; StudentMember and StaffMember inherit from Member.
Extend the system without editing any existing class: add a PremiumMember (limit 10) and a NoFine strategy (always 0). Borrow three books with a premium member, return one 10 days late with NoFine, and log the fine.
Common interview questions
- What is object-oriented programming?
- What is the difference between a class and an object?
- Explain the four pillars of OOP.
- What is a constructor?
- How is procedural programming different from OOP?
- What are fields, properties and methods?
- What do access modifiers do?
- What is a static member?
- What does the this keyword refer to?
- What is the difference between encapsulation and abstraction?
- Method overloading vs method overriding?
- Abstract class vs interface — when do you use each?
- What does “favour composition over inheritance” mean?
- Association, aggregation and composition — what’s the difference?
- What is inheritance, and what are its risks?
- Virtual vs abstract methods?
- What is dependency injection, in OOP terms?
- Explain the Single Responsibility Principle with an example.
- What does the Open/Closed Principle mean in practice?
- What is the Interface Segregation Principle?
- What is the Dependency Inversion Principle?
- Explain the SOLID principles.
- Why is a Square inheriting from Rectangle a classic LSP violation?
- Explain the Singleton pattern and its drawbacks.
- What is the Strategy pattern?
- What is the Factory pattern and when is it useful?
- What is the Observer pattern?
- What is the Repository pattern?
- How do you read a UML class diagram?