Object-Oriented Programming — Quick Summary
Quick revision: every topic, key terms, and mnemonics for Object-Oriented Programming.
This is a quick revision doc covering all 29 topics in the OOP collection — half JavaScript, half Python. Open the linked notes if you want depth. The four pillars (encapsulation, inheritance, polymorphism, abstraction) are spread throughout — pay attention to how each language realizes them.
OOP Pillars (cross-language quick map)
| Pillar | JavaScript | Python |
|---|---|---|
| Encapsulation | #privateField, closures, WeakMap, _underscore | _protected, __mangled, @property |
| Inheritance | class Child extends Parent, super() | class Child(Parent):, super().__init__() |
| Polymorphism | Method overriding + duck typing | Method overriding + duck typing + dunder ops |
| Abstraction | Throw in base methods, new.target, factories | abc.ABC + @abstractmethod, Protocol |
Remember. “EIPA — Every Interview Picks A pillar.”
JavaScript
Objects Fundamentals
What it is. Object literals {key: value}. Properties accessed via dot or bracket notation; bracket required for dynamic keys / special chars. Methods are properties whose value is a function.
Key terms.
- Computed keys —
{ [field]: value },{ [${field}Verified]: true }. - Shorthand —
{ name, age }when names match. Object.keys/values/entries,Object.assign(target, ...sources)(or spread).Object.freeze— fully immutable (shallow).Object.seal— no add/remove, mutation OK.invshasOwnPropertyvs modernObject.hasOwn.delete obj.k— removes own property.
Constructor Functions & the new Keyword
What it is. Pre-class blueprint for instances. Capitalized name + called with new.
new does 4 things. 1) creates {}, 2) links proto to Fn.prototype, 3) calls Fn.call(newObj, ...args), 4) returns this (unless an object is explicitly returned).
Key terms.
- Forgetting
new—thisbecomes global; properties leak. Classes throw instead. - Object return replaces
this. Primitive return is ignored. instanceof— walks proto chain checking forFn.prototype.- Factory function — returns plain object via closures; no
new, nothis, noinstanceofsupport.
Remember. “new makes object, links proto, runs ctor, returns this.”
Prototypes & the Prototype Chain
What it is. Each object has a hidden [[Prototype]] linking to another object. Property lookup walks the chain until found or until null.
Key terms.
__proto__/Object.getPrototypeOf(obj)— the link itself; lives on every object.Fn.prototype— only on functions; the object thatnew Fn()instances will link to.Object.create(proto)— make a new object with a chosen prototype (ornull).- Property shadowing — own property hides one on the chain.
- Chain end —
Object.prototype→null.
Remember. “__proto__ is the link. prototype is the stencil.”
ES6 Classes
What it is. Sugar over constructor + prototype. typeof Class === "function".
Key terms.
- Methods — go on
prototype, non-enumerable. staticfields/methods — belong to the class, not instances.- Class expressions —
const C = class {};. - Hoisting — classes are in the TDZ; can’t use before declaration (unlike function decls).
- No-
newerror —Class()throws “cannot be invoked without ‘new’”. - Public class fields —
count = 0;defined per instance.
Inheritance: extends & super
What it is. class Dog extends Animal { ... }. super(...) calls parent constructor; super.method() calls parent method.
Key terms.
- Must call
super()beforethisin a child constructor. - Method overriding — child’s same-named method wins.
- Static inheritance works too.
instanceof— true for child, parent, and Object.- Multi-level — possible, but prefer composition past 2-3 levels.
Remember. “super first, this second. Forget super, get ReferenceError.”
Encapsulation & Private Fields
What it is. Hide internals. JS gives several mechanisms.
| Approach | True privacy | Works with class | Notes |
|---|---|---|---|
#field (ES2022) | Yes (engine-enforced SyntaxError) | Yes | Modern default |
| Closures | Yes | No (factory only) | No prototype sharing |
| WeakMap | Yes | Yes | Pre-ES2022 trick |
_underscore | No (convention) | Yes | Just naming |
| Symbol keys | Pseudo (findable via getOwnPropertySymbols) | Yes | Hidden from Object.keys |
Remember. “# for new code; closures for factories; everything else is legacy.”
Polymorphism in JavaScript
What it is. Same interface, different behavior.
Key terms.
- Method overriding — child redefines parent’s method (
Circle.areavsRectangle.area). - Duck typing — call the method; trust it’s there. No interfaces required.
toString/valueOf— control string/number coercion.Symbol.toPrimitive(hint)— full control of+obj,${obj}. BeatstoString/valueOf.Symbol.hasInstance— customizeinstanceof.
Remember. “If it has the method, just call it.”
Abstraction Patterns
What it is. Hide complexity, expose a simple interface. JS has no abstract keyword.
Key terms.
- Throw in base —
throw new Error("Subclass must implement X()"). new.target— block direct instantiation:if (new.target === Shape) throw ....- Factory functions — caller asks for behavior, doesn’t see internals.
Symbol.species— control which class derived methods (map,filter) instantiate.
Remember. “Don’t abstract until a second implementation actually shows up.”
this Keyword & Execution Context
What it is. Determined by how the function is called.
Decision tree.
- Arrow function? → lexical
this(from surrounding scope). Can’t be changed. - Called with
new? → new instance. call/apply/bind? → whatever you pass.obj.method()? →obj.- Plain
fn()? →undefined(strict) /window(sloppy).
Common pitfall. Method passed as callback loses this. Fix: arrow function or .bind(this).
Remember. “Look at the call site, not the definition.”
Getters, Setters & Proxy
What it is.
get/setin object literals or classes — computed/validated property access.Object.defineProperty— low-level descriptor configuration.Proxy(target, handler)— intercepts ANY operation (get,set,has,deleteProperty,apply, …).Reflect— methods that match each Proxy trap and provide proper default behavior; use inside trap implementations.
Remember. Vue 3 reactivity = Proxy. “Getters/setters for one prop; Proxy for all.”
Mixins & Composition over Inheritance
What it is. Inheritance creates rigid trees and the fragile base class problem. Composition mixes capabilities.
Key terms.
Object.assign(Class.prototype, mixin1, mixin2)— straight method copy.- Functional mixin —
Mixin = (Base) => class extends Base { ... }. Stack:class X extends A(B(Base)) {}. - Delegation — class HAS another object and forwards calls (Car has Engine).
- Closure-based composition — pure functions, no
this, true privacy.
Remember. “Inheritance = is-a. Composition = has-a. When in doubt, has-a.”
Symbols & Well-Known OOP Protocols
What it is. Unique primitive used as property keys. Well-known Symbols hook into language-level operations.
| Symbol | Triggered by |
|---|---|
Symbol.iterator | for...of, spread, destructuring |
Symbol.toPrimitive | +obj, ${obj}, comparisons |
Symbol.hasInstance | obj instanceof X |
Symbol.species | .map(), .filter(), .then() derived constructors |
Symbol.toStringTag | Object.prototype.toString.call(obj) → [object X] |
Remember. Generator method shorthand: *[Symbol.iterator]() { yield ... }.
SOLID Principles in JavaScript
S–O–L–I–D. “Single, Open, Liskov, Interface, Dependency.”
| Principle | One-liner | JS pattern | |
|---|---|---|---|
| S | Single Responsibility | One class, one reason to change | Split big class into focused modules |
| O | Open/Closed | Extend without modifying | Strategy / plugin / each shape calculates its own area |
| L | Liskov Substitution | Subclasses honor parent’s promises | Don’t override to break fly() |
| I | Interface Segregation | Small focused contracts | Role-based mixins (Walkable, Swimmable) |
| D | Dependency Inversion | Depend on abstractions | Inject dependencies via constructor |
Remember. Penguin can’t fly → restructure (FlyingBird subclass). Don’t throw inside fly().
OOP Design Patterns in JavaScript
Seven core patterns and idiomatic implementations.
| Pattern | Category | Idea | Real-world |
|---|---|---|---|
| Singleton | Creational | One instance globally | Module exports, Redux store |
| Factory | Creational | Hide creation logic | React.createElement, express() |
| Builder | Creational | Fluent step-by-step (return this) | Knex.js |
| Observer (pub/sub) | Behavioral | Subscribe + emit | EventEmitter, addEventListener |
| Strategy | Behavioral | Pluggable algorithm (just pass a function) | Sort comparators, tax rules |
| Decorator | Structural | Wrap to add behavior | Express middleware, HOFs |
| Proxy | Structural | Control access | Caching, Vue reactivity |
Remember. “Functions are first-class — half the GoF patterns disappear.”
Python
Classes & Instances
What it is. class Foo: blueprint. __init__(self, ...) initializes. __new__ actually creates.
Key terms.
self— current instance, passed automatically.- Class attribute vs instance attribute — class attrs shared, instance attrs per-object (set via
self.x = ...). - Attribute lookup order — instance
__dict__→ class__dict__→ parents (MRO) → AttributeError. - Shadowing — assigning on instance creates a fresh instance attr.
type(obj)vsisinstance(obj, Cls)— preferisinstance(respects subclasses).__dict__— peek at the attributes dict.
Method Types: Instance, Class & Static
What it is.
| Method | First arg | Use |
|---|---|---|
| Instance | self | Read/modify state |
@classmethod | cls | Alternative constructors / factories. cls(...) respects subclass. |
@staticmethod | nothing | Utility helper namespaced under class |
Remember. “self for me, cls for my class, staticmethod for nothing extra.”
Inheritance & MRO
What it is. class Child(Parent):. super().__init__(...) calls parent.
Key terms.
- Multiple inheritance —
class D(B, C):. - Diamond problem — D → B,C → A. Whose method?
- C3 linearization — Python’s deterministic MRO. Children before parents, parent order preserved (B before C).
Cls.mro()— inspect:[D, B, C, A, object].super()follows MRO — not just “the parent”. For cooperative MI, every class mustsuper().__init__(**kwargs).
Remember. “MRO walks left-to-right, kids before parents.”
Encapsulation & Name Mangling
What it is. Three conventions:
| Name | Meaning |
|---|---|
name | Public |
_name | ”Internal — please don’t touch” (convention only). from x import * skips these. |
__name | Name-mangled to _ClassName__name. NOT private — just renamed to avoid subclass clashes. |
__name__ | Dunders (trailing underscores) are NOT mangled. |
The Pythonic way. _attribute + @property for real validation. Don’t reach for __double unless you’re avoiding subclass collision.
Remember. “We’re all consenting adults here.”
Polymorphism & Duck Typing
What it is. Same call, different behavior.
Key terms.
- Method overriding —
class Circle(Shape)redefinesarea(). - Duck typing — no shared parent needed; if it has
.speak(), it speaks. - EAFP > LBYL — try first, catch error. Pythonic.
- Operator overloading via dunders (
__add__,__lt__, …). - No method overloading by parameter count — last def wins. Use
*argsor defaults. functools.singledispatch— dispatch by argument type for functions;singledispatchmethodfor methods.
Remember. “If it walks like a duck…”
Dunder Methods Deep Dive
What it is. Hooks into Python’s data model.
Key dunders.
- Display —
__repr__(devs, unambiguous),__str__(users; falls back to__repr__),__format__(format()and f-strings). - Comparison —
__eq__,__lt__, etc. ReturningNotImplementedlets Python try the other side.functools.total_orderingfills in the rest from__eq__+__lt__. __eq__/__hash__contract — defining__eq__sets__hash__ = Noneautomatically. Define__hash__to remain hashable:hash((self.x, self.y)).- Arithmetic —
__add__,__radd__(when other doesn’t know how — needed forsum()),__iadd__(+=). - Container —
__len__,__getitem__,__setitem__,__contains__,__iter__. - Callable —
__call__. - Context manager —
__enter__/__exit__. - Boolean —
__bool__; falls back to__len__if absent.
Property Decorators & Descriptors
What it is. @property for clean attribute-style getters; @x.setter and @x.deleter to allow assign/del.
Read-only. Just @property with no setter.
Descriptor protocol. Any object with __get__/__set__/__delete__ is a descriptor. When stored on a class, attribute access goes through it.
Key terms.
__set_name__(self, owner, name)(3.6+) — descriptor learns the attribute name automatically.- Data descriptor — has
__set__. Wins over instance__dict__. - Non-data descriptor — only
__get__. Loses to instance__dict__(so methods can be shadowed).
Remember. Custom descriptor when reusing the same validation across many fields.
Abstract Classes & ABC
What it is. from abc import ABC, abstractmethod. Subclass that doesn’t implement an abstract method can’t be instantiated → TypeError.
Key terms.
- Abstract property — combine
@propertyabove@abstractmethod. - Concrete methods — abstract base can still ship shared methods.
Drawable.register(SomeClass)— virtual subclass; declares satisfaction without inheritance, but no enforcement.ABCvsProtocolvs duck typing — strict / structural / informal.
Remember. ABCs raise at instantiation time — early failure is the whole point.
Dataclasses & NamedTuple
What it is. Auto-generate __init__, __repr__, __eq__ from typed fields.
Key terms.
@dataclass— defaults are mutable instances.field(default_factory=list)— for mutable defaults (lists/dicts).field(init=False, repr=False, compare=False)— fine-grained control.__post_init__— extra setup after auto__init__(computed fields).@dataclass(frozen=True)— immutable + hashable.@dataclass(slots=True, kw_only=True)(3.10+) — memory + force keyword args.NamedTuple— immutable, tuple-like, supports indexing AND.name. Hashable by default.
Remember. Dataclass for mutable records. NamedTuple for immutable tuples-with-names.
slots & Memory Optimization
What it is. __slots__ = ("x", "y") replaces per-instance __dict__ with fixed-offset slots. ~3x less memory, faster attribute access.
Trade-offs.
- No dynamic attributes (
obj.z = 1→ AttributeError). - No
__dict__(sovars()breaks). - Inheritance: every class needs
__slots__; child lists ONLY new attrs. - Add
'__dict__'in slots to keep some flexibility (kills the savings). @dataclass(slots=True)— easiest path.
Remember. Use it when creating millions of instances of the same shape.
Composition vs Inheritance
What it is. Same debate as JS, expressed in Python.
Key terms.
- Is-a → inheritance (Cat IS Animal).
- Has-a → composition (Car HAS Engine).
- Fragile base class — parent change breaks all kids.
- Gorilla-banana — inherit a banana, get the gorilla holding the banana and the jungle.
- Delegation — UserService HAS-A Logger; forwards
log()calls. Notclass UserService(Logger):(a user service IS NOT a logger). - Mixins — small, orthogonal, multiple-inheritance friendly (
JsonMixin,LogMixin).
Remember. “Default to composition. Use inheritance for true is-a only.”
Metaclasses
What it is. A class whose instances are classes. type is the default metaclass.
Chain. type creates Dog → Dog creates buddy. So type(buddy) == Dog, type(Dog) == type, type(type) == type.
Key terms.
- Dynamic class creation —
type(name, bases, namespace). - Custom metaclass —
class Meta(type): def __new__(mcs, name, bases, ns): .... __new__vs__init__in metaclasses —__new__runs before the class exists (modify namespace),__init__runs after (registration/validation).__init_subclass__(3.6+) — simpler hook, no metaclass needed for most subclass-tracking use cases.- Class decorator — even simpler way to modify a single class.
Real uses. Django ORM, SQLAlchemy, ABCMeta, EnumMeta.
Remember. “If you wonder whether you need one, you don’t.” — Tim Peters.
Protocols & Structural Subtyping
What it is. from typing import Protocol. Static duck typing. No inheritance — match the shape, type checker validates.
Key terms.
- Nominal vs structural — “who you are” vs “what you can do”.
- Attribute protocol —
name: strfield requirements supported. @runtime_checkable— enablesisinstance(x, Drawable)at runtime (only checks method existence, not signatures).- Built-in protocols —
Sized,Iterable,Hashable,Reversible,SupportsFloat,SupportsAbs… - Composition — protocols can extend each other (
class ReadWrite(Readable, Writable, Protocol)).
ABC vs Protocol. ABC = inheritance + runtime enforcement. Protocol = no inheritance + static (or opt-in runtime) checks.
Remember. Repository pattern + Protocol = swap PostgresRepo for InMemoryRepo in tests with zero ceremony.
SOLID Principles in Python
Same five principles, idiomatic Python.
- S — small classes & modules; “module = unit of responsibility”.
- O — Protocols + first-class functions remove the need for big inheritance trees.
- L — restructure hierarchies so contracts hold (Penguin doesn’t fly).
- I — small Protocols (Coder, Tester, Designer) > one fat ABC.
- D — constructor injection with Protocol types. No DI framework needed in Python.
Remember. “Modules + Protocols + first-class functions = SOLID for free.”
OOP Design Patterns in Python
Eight patterns, the Pythonic way.
| Pattern | Pythonic implementation |
|---|---|
| Singleton | Module-level instance (preferred) or __new__ override |
| Factory | @classmethod alternative constructors (User.admin(name), from_dict(data)) |
| Builder | Fluent chaining: each method return self |
| Observer | Dict of event → list of callbacks; emit(event, *args) |
| Strategy | Pass a function as a parameter |
| Decorator | @deco syntax (function or class with __call__) |
| Iterator | __iter__ + __next__, but generators replace most cases |
| Template Method | ABC with concrete run() calling abstract steps (extract → transform → load) |
Remember. “Patterns survive in Python — the ceremony doesn’t.”