/

[work in progress]
https://www.interviewbit.com/oops-interview-questions/
some concepts: Encapsulation, Inheritance, Polymorphism, Abstraction, Composition, etc.
Class: A blueprint for creating objects Object: An instance of a class
class Dog:
def __init__(self, name: str):
self.name = name
def bark(self) -> str:
return f"{self.name} says woof!"
# 2. Object creation
my_dog = Dog("Buddy")
print(my_dog.bark()) # "Buddy says woof!"Bundling data and methods that operate on that data within a single unit (class). Hide internal details.
class BankAccount:
def __init__(self, balance: float):
self._balance = balance # Protected attribute (convention)
def deposit(self, amount: float) -> None:
if amount > 0:
self._balance += amount
def get_balance(self) -> float:
return self._balance
# External code can't directly modify _balance improperlyCreate new classes based on existing ones, inheriting attributes and methods.
class Animal:
def __init__(self, name: str):
self.name = name
def speak(self) -> str:
raise NotImplementedError("Subclass must implement")
class Dog(Animal):
def speak(self) -> str:
return f"{self.name} barks"
class Cat(Animal):
def speak(self) -> str:
return f"{self.name} meows"Objects of different classes can be treated as objects of a common parent class. Same interface, different implementations.
def make_animal_speak(animal: Animal) -> None:
print(animal.speak())
dog = Dog("Buddy")
cat = Cat("Whiskers")
make_animal_speak(dog) # Works with Dog
make_animal_speak(cat) # Works with Cat
# 3. Both have speak() method but behave differentlyHide complex implementation details, expose only necessary features.
from abc import ABC, abstractmethod
class PaymentProcessor(ABC):
@abstractmethod
def process_payment(self, amount: float) -> bool:
"""Process payment - subclasses define how"""
pass
class CreditCardProcessor(PaymentProcessor):
def process_payment(self, amount: float) -> bool:
# Complex credit card logic hidden here
print(f"Processing ${amount} via credit card")
return True
class PayPalProcessor(PaymentProcessor):
def process_payment(self, amount: float) -> bool:
# Complex PayPal API logic hidden here
print(f"Processing ${amount} via PayPal")
return True
# 4. Client code doesn't care about implementation details
processor: PaymentProcessor = CreditCardProcessor()
processor.process_payment(100.00)“Has-a” relationship. Build complex objects from simpler ones.
class Engine:
def start(self) -> str:
return "Engine started"
class Car:
def __init__(self):
self.engine = Engine() # Car HAS-A Engine
def start(self) -> str:
return self.engine.start()
# 5. Prefer composition over inheritance when possible