A Comprehensive Tree Diagram of OOP Concepts with Examples
Class: Blueprint/template that defines the structure and behavior.
Object: Instance of a class created with the new keyword.
class Car {
public string Brand;
public string Model;
public int Year;
public void Drive() {
Console.WriteLine($"{Brand} {Model} is driving...");
}
}
class Program {
static void Main() {
// Creating objects
Car car1 = new Car();
car1.Brand = "Toyota";
car1.Model = "Camry";
car1.Year = 2022;
car1.Drive();
Car car2 = new Car {
Brand = "Tesla",
Model = "Model 3",
Year = 2023
};
car2.Drive();
}
}
// Class with methods and properties
class BankAccount {
private string accountNumber;
private decimal balance;
public BankAccount(string accNumber, decimal initialBalance) {
accountNumber = accNumber;
balance = initialBalance;
}
public void Deposit(decimal amount) {
if (amount > 0) {
balance += amount;
Console.WriteLine($"Deposited: ${amount}. New balance: ${balance}");
}
}
public void Withdraw(decimal amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
Console.WriteLine($"Withdrew: ${amount}. New balance: ${balance}");
} else {
Console.WriteLine("Insufficient funds or invalid amount");
}
}
public decimal GetBalance() => balance;
}
class Program {
static void Main() {
BankAccount account = new BankAccount("123456789", 1000);
account.Deposit(500);
account.Withdraw(200);
account.Withdraw(2000); // Should fail
Console.WriteLine($"Final balance: ${account.GetBalance()}");
}
}
Definition: Binding data & methods into a class and controlling access using Access Modifiers.
Types of Access Modifiers:
class Person {
private string ssn = "123-45-6789"; // private field
public string Name { get; set; } // public property
protected int Age { get; set; } // protected property
internal string City { get; set; } // internal property
// Method to access private field
public string GetSSN() {
return "XXX-XX-" + ssn.Substring(ssn.Length - 4);
}
}
class Program {
static void Main() {
Person person = new Person();
person.Name = "John Doe"; // OK - public
person.City = "New York"; // OK - internal (same assembly)
// person.Age = 30; // Error - protected
// person.ssn = "987-65-4321"; // Error - private
Console.WriteLine(person.GetSSN()); // Access via method
}
}
class Employee {
private string _name;
private decimal _salary;
public string Name {
get { return _name; }
set {
if (!string.IsNullOrWhiteSpace(value))
_name = value;
else
throw new ArgumentException("Name cannot be empty");
}
}
public decimal Salary {
get { return _salary; }
set {
if (value >= 0)
_salary = value;
else
throw new ArgumentException("Salary cannot be negative");
}
}
public string Department { get; set; }
public Employee(string name, decimal salary, string department) {
Name = name;
Salary = salary;
Department = department;
}
public void GiveRaise(decimal percentage) {
if (percentage > 0 && percentage <= 50) {
Salary += Salary * (percentage / 100);
Console.WriteLine($"{Name} received a {percentage}% raise. New salary: ${Salary}");
} else {
Console.WriteLine("Invalid raise percentage");
}
}
}
class Program {
static void Main() {
try {
Employee emp = new Employee("Alice Johnson", 50000, "Engineering");
Console.WriteLine($"Employee: {emp.Name}, Salary: ${emp.Salary}");
emp.GiveRaise(10);
// This will throw an exception
// emp.Salary = -1000;
} catch (Exception ex) {
Console.WriteLine($"Error: {ex.Message}");
}
}
}
Definition: Reusing features of one class in another.
Types:
// Single inheritance
class Animal {
public string Name { get; set; }
public void Eat() {
Console.WriteLine($"{Name} is eating.");
}
}
class Dog : Animal {
public void Bark() {
Console.WriteLine($"{Name} is barking.");
}
}
// Multilevel inheritance
class Puppy : Dog {
public void Weep() {
Console.WriteLine($"{Name} is weeping.");
}
}
// Multiple inheritance via interfaces
interface IFly {
void Fly();
}
interface ISwim {
void Swim();
}
class Duck : Animal, IFly, ISwim {
public void Fly() {
Console.WriteLine($"{Name} is flying.");
}
public void Swim() {
Console.WriteLine($"{Name} is swimming.");
}
}
class Program {
static void Main() {
// Single inheritance
Dog dog = new Dog { Name = "Buddy" };
dog.Eat();
dog.Bark();
// Multilevel inheritance
Puppy puppy = new Puppy { Name = "Max" };
puppy.Eat();
puppy.Bark();
puppy.Weep();
// Multiple interfaces
Duck duck = new Duck { Name = "Donald" };
duck.Eat();
duck.Fly();
duck.Swim();
}
}
class Vehicle {
public string Brand { get; set; }
public int Year { get; set; }
public Vehicle(string brand, int year) {
Brand = brand;
Year = year;
}
public virtual void Start() {
Console.WriteLine($"{Brand} vehicle starting...");
}
}
class Car : Vehicle {
public int Doors { get; set; }
public Car(string brand, int year, int doors) : base(brand, year) {
Doors = doors;
}
public override void Start() {
base.Start(); // Call base method
Console.WriteLine($"Car with {Doors} doors is ready to go!");
}
}
class Motorcycle : Vehicle {
public bool HasSideCar { get; set; }
public Motorcycle(string brand, int year, bool hasSideCar) : base(brand, year) {
HasSideCar = hasSideCar;
}
public override void Start() {
Console.WriteLine($"{Brand} motorcycle is revving up!");
if (HasSideCar) {
Console.WriteLine("Sidecar attached.");
}
}
}
class Program {
static void Main() {
Vehicle vehicle = new Vehicle("Generic", 2020);
vehicle.Start();
Car car = new Car("Toyota", 2022, 4);
car.Start();
Motorcycle bike = new Motorcycle("Harley", 2021, true);
bike.Start();
// Polymorphism in action
Vehicle[] vehicles = {
new Vehicle("Generic", 2020),
new Car("Honda", 2022, 2),
new Motorcycle("Yamaha", 2021, false)
};
foreach (var v in vehicles) {
v.Start();
Console.WriteLine("---");
}
}
}
Definition: Same method name, different behavior.
Types:
// Method overloading (compile-time polymorphism)
class Calculator {
public int Add(int a, int b) {
return a + b;
}
public double Add(double a, double b) {
return a + b;
}
public int Add(int a, int b, int c) {
return a + b + c;
}
public string Add(string a, string b) {
return a + b;
}
}
// Method overriding (runtime polymorphism)
class Animal {
public virtual void Speak() {
Console.WriteLine("Animal makes a sound");
}
}
class Dog : Animal {
public override void Speak() {
Console.WriteLine("Dog barks: Woof woof!");
}
}
class Cat : Animal {
public override void Speak() {
Console.WriteLine("Cat meows: Meow meow!");
}
}
class Program {
static void Main() {
// Overloading example
Calculator calc = new Calculator();
Console.WriteLine(calc.Add(5, 10));
Console.WriteLine(calc.Add(5.5, 2.3));
Console.WriteLine(calc.Add(1, 2, 3));
Console.WriteLine(calc.Add("Hello, ", "World!"));
// Overriding example
Animal animal = new Animal();
Animal dog = new Dog();
Animal cat = new Cat();
animal.Speak();
dog.Speak();
cat.Speak();
// Polymorphism in action
Animal[] animals = {
new Animal(),
new Dog(),
new Cat()
};
foreach (Animal a in animals) {
a.Speak();
}
}
}
abstract class Shape {
public abstract double Area();
public abstract double Perimeter();
public void Display() {
Console.WriteLine($"Shape Area: {Area():F2}, Perimeter: {Perimeter():F2}");
}
}
class Circle : Shape {
public double Radius { get; set; }
public Circle(double radius) {
Radius = radius;
}
public override double Area() {
return Math.PI * Radius * Radius;
}
public override double Perimeter() {
return 2 * Math.PI * Radius;
}
}
class Rectangle : Shape {
public double Width { get; set; }
public double Height { get; set; }
public Rectangle(double width, double height) {
Width = width;
Height = height;
}
public override double Area() {
return Width * Height;
}
public override double Perimeter() {
return 2 * (Width + Height);
}
}
class Triangle : Shape {
public double SideA { get; set; }
public double SideB { get; set; }
public double SideC { get; set; }
public Triangle(double a, double b, double c) {
SideA = a;
SideB = b;
SideC = c;
}
public override double Area() {
// Using Heron's formula
double s = (SideA + SideB + SideC) / 2;
return Math.Sqrt(s * (s - SideA) * (s - SideB) * (s - SideC));
}
public override double Perimeter() {
return SideA + SideB + SideC;
}
}
class Program {
static void Main() {
Shape[] shapes = {
new Circle(5),
new Rectangle(4, 6),
new Triangle(3, 4, 5)
};
foreach (Shape shape in shapes) {
shape.Display();
}
}
}
Definition: Hiding implementation, showing only important details.
Types:
// Abstract Class example
abstract class Shape {
public abstract void Draw();
public void Display() {
Console.WriteLine("Displaying shape:");
Draw();
}
}
class Circle : Shape {
public override void Draw() {
Console.WriteLine("Drawing a circle");
}
}
class Square : Shape {
public override void Draw() {
Console.WriteLine("Drawing a square");
}
}
// Interface example
interface IDatabase {
void Connect();
void Disconnect();
void ExecuteQuery(string query);
}
class MySQLDatabase : IDatabase {
public void Connect() {
Console.WriteLine("Connecting to MySQL database...");
}
public void Disconnect() {
Console.WriteLine("Disconnecting from MySQL database...");
}
public void ExecuteQuery(string query) {
Console.WriteLine($"Executing MySQL query: {query}");
}
}
class SQLServerDatabase : IDatabase {
public void Connect() {
Console.WriteLine("Connecting to SQL Server database...");
}
public void Disconnect() {
Console.WriteLine("Disconnecting from SQL Server database...");
}
public void ExecuteQuery(string query) {
Console.WriteLine($"Executing SQL Server query: {query}");
}
}
class Program {
static void Main() {
// Abstract class usage
Shape circle = new Circle();
Shape square = new Square();
circle.Display();
square.Display();
// Interface usage
IDatabase mysql = new MySQLDatabase();
IDatabase sqlserver = new SQLServerDatabase();
mysql.Connect();
mysql.ExecuteQuery("SELECT * FROM users");
mysql.Disconnect();
Console.WriteLine();
sqlserver.Connect();
sqlserver.ExecuteQuery("SELECT * FROM products");
sqlserver.Disconnect();
}
}
interface IPrintable {
void Print();
}
interface IScannable {
void Scan();
}
interface IFaxable {
void Fax();
}
// Basic printer implements only IPrintable
class BasicPrinter : IPrintable {
public void Print() {
Console.WriteLine("Printing document...");
}
}
// Advanced printer implements multiple interfaces
class AdvancedPrinter : IPrintable, IScannable, IFaxable {
public void Print() {
Console.WriteLine("High-quality printing...");
}
public void Scan() {
Console.WriteLine("Scanning document...");
}
public void Fax() {
Console.WriteLine("Sending fax...");
}
}
// Multi-function device
class MultiFunctionDevice : IPrintable, IScannable {
public void Print() {
Console.WriteLine("Multi-function device printing...");
}
public void Scan() {
Console.WriteLine("Multi-function device scanning...");
}
public void Copy() {
Console.WriteLine("Copying document...");
Scan();
Print();
}
}
class Program {
static void Main() {
Console.WriteLine("Basic Printer:");
BasicPrinter basic = new BasicPrinter();
basic.Print();
Console.WriteLine("\nAdvanced Printer:");
AdvancedPrinter advanced = new AdvancedPrinter();
advanced.Print();
advanced.Scan();
advanced.Fax();
Console.WriteLine("\nMulti-Function Device:");
MultiFunctionDevice mfd = new MultiFunctionDevice();
mfd.Copy();
// Using interfaces as types
IPrintable[] printers = {
new BasicPrinter(),
new AdvancedPrinter(),
new MultiFunctionDevice()
};
Console.WriteLine("\nAll printers printing:");
foreach (IPrintable printer in printers) {
printer.Print();
}
}
}
Definition: Special method called at object creation to initialize values.
Types:
class Person {
public string Name;
public int Age;
public string City;
// Default constructor
public Person() {
Name = "Unknown";
Age = 0;
City = "Unknown";
}
// Parameterized constructor
public Person(string name, int age) {
Name = name;
Age = age;
City = "Unknown";
}
// Parameterized constructor with all parameters
public Person(string name, int age, string city) {
Name = name;
Age = age;
City = city;
}
// Copy constructor
public Person(Person other) {
Name = other.Name;
Age = other.Age;
City = other.City;
}
public void Display() {
Console.WriteLine($"Name: {Name}, Age: {Age}, City: {City}");
}
}
class Program {
static void Main() {
// Using different constructors
Person person1 = new Person(); // Default
Person person2 = new Person("John", 25); // Parameterized
Person person3 = new Person("Alice", 30, "New York"); // Parameterized
Person person4 = new Person(person3); // Copy constructor
person1.Display();
person2.Display();
person3.Display();
person4.Display();
}
}
class Configuration {
private static Configuration instance;
private static readonly object lockObject = new object();
public string DatabaseConnection { get; set; }
public string AppName { get; set; }
public int MaxConnections { get; set; }
// Private constructor for singleton pattern
private Configuration() {
// Load configuration from file or environment
DatabaseConnection = "Server=localhost;Database=myDB;User=admin;";
AppName = "My Application";
MaxConnections = 100;
}
// Static constructor
static Configuration() {
Console.WriteLine("Configuration class initialized");
}
// Public method to get singleton instance
public static Configuration GetInstance() {
lock (lockObject) {
if (instance == null) {
instance = new Configuration();
}
return instance;
}
}
public void DisplayConfig() {
Console.WriteLine($"App: {AppName}");
Console.WriteLine($"DB Connection: {DatabaseConnection}");
Console.WriteLine($"Max Connections: {MaxConnections}");
}
}
class Logger {
// Static field
private static int instanceCount = 0;
// Static constructor
static Logger() {
Console.WriteLine("Logger class initialized");
}
// Instance constructor
public Logger() {
instanceCount++;
Console.WriteLine($"Logger instance created. Total instances: {instanceCount}");
}
public void Log(string message) {
Console.WriteLine($"[LOG] {message}");
}
}
class Program {
static void Main() {
Console.WriteLine("Starting application...");
// Singleton usage
Configuration config = Configuration.GetInstance();
config.DisplayConfig();
Configuration config2 = Configuration.GetInstance();
Console.WriteLine($"Are both configurations the same instance? {config == config2}");
// Logger with static constructor
Logger logger1 = new Logger();
logger1.Log("First message");
Logger logger2 = new Logger();
logger2.Log("Second message");
}
}
Definition: Safe way to access private fields with get and set accessors.
Types:
class Person {
// Field-backed property with validation
private string name;
public string Name {
get { return name; }
set {
if (!string.IsNullOrWhiteSpace(value))
name = value;
else
throw new ArgumentException("Name cannot be empty");
}
}
// Field-backed property with validation
private int age;
public int Age {
get { return age; }
set {
if (value >= 0 && value <= 120)
age = value;
else
throw new ArgumentException("Age must be between 0 and 120");
}
}
// Auto-implemented property
public string City { get; set; }
// Read-only property
public bool IsAdult {
get { return Age >= 18; }
}
// Computed property
public string Description {
get {
return $"{Name}, {Age} years old, from {City}";
}
}
// Write-only property (rarely used)
private string secret;
public string Secret {
set { secret = value; }
}
}
class Program {
static void Main() {
Person person = new Person();
person.Name = "John Doe";
person.Age = 25;
person.City = "New York";
// person.Secret = "My secret"; // Can set but not get
Console.WriteLine(person.Name);
Console.WriteLine(person.Age);
Console.WriteLine(person.City);
Console.WriteLine($"Is adult: {person.IsAdult}");
Console.WriteLine(person.Description);
try {
person.Age = 150; // This will throw an exception
} catch (ArgumentException ex) {
Console.WriteLine($"Error: {ex.Message}");
}
}
}
class Team {
private string[] players = new string[11];
// Indexer property
public string this[int index] {
get {
if (index >= 0 && index < players.Length)
return players[index];
else
throw new IndexOutOfRangeException();
}
set {
if (index >= 0 && index < players.Length)
players[index] = value;
else
throw new IndexOutOfRangeException();
}
}
// Another indexer with different parameter type
public string this[string position] {
get {
switch (position.ToLower()) {
case "goalkeeper": return players[0];
case "defender": return players[1];
case "midfielder": return players[5];
case "forward": return players[9];
default: return "Unknown position";
}
}
set {
switch (position.ToLower()) {
case "goalkeeper": players[0] = value; break;
case "defender": players[1] = value; break;
case "midfielder": players[5] = value; break;
case "forward": players[9] = value; break;
default: throw new ArgumentException("Unknown position");
}
}
}
public void ListPlayers() {
for (int i = 0; i < players.Length; i++) {
if (!string.IsNullOrEmpty(players[i]))
Console.WriteLine($"Player {i}: {players[i]}");
}
}
}
class Rectangle {
public double Length { get; set; }
public double Width { get; set; }
// Computed property
public double Area {
get { return Length * Width; }
}
// Computed property
public double Perimeter {
get { return 2 * (Length + Width); }
}
// Method that returns a computed value
public double Diagonal {
get { return Math.Sqrt(Length * Length + Width * Width); }
}
}
class Program {
static void Main() {
// Indexer example
Team team = new Team();
team[0] = "John (Goalkeeper)";
team[1] = "Mike (Defender)";
team[5] = "Steve (Midfielder)";
team[9] = "Alex (Forward)";
team.ListPlayers();
Console.WriteLine($"Goalkeeper: {team["goalkeeper"]}");
Console.WriteLine($"Forward: {team["forward"]}");
// Computed properties example
Rectangle rect = new Rectangle { Length = 10, Width = 5 };
Console.WriteLine($"Rectangle: {rect.Length}x{rect.Width}");
Console.WriteLine($"Area: {rect.Area}");
Console.WriteLine($"Perimeter: {rect.Perimeter}");
Console.WriteLine($"Diagonal: {rect.Diagonal:F2}");
}
}