home
›
cheatsheets
›
computer_science
›
oop
Free to read Every card and diagram, and Quiz me
2
Free account Star cards. Your Quiz me marks are kept, so next time you drill just what you missed
3
Pro All 85 answers on this sheet, My sheet across every topic, and PDFs
A free account keeps your stars and Quiz me marks. Pro adds all 85 answers on this sheet, My sheet across every topic, and PDFs.
/
Read
Quiz me
Comfortable
Compact
My misses 0
Click any code to copy it
Done 0 /0
To review 0
On this sheet
The model
01 Objects & the four pillars02 Encapsulation & abstraction03 Inheritance & interfaces04 Polymorphism & overriding05 Composition & coupling06 Equality & hashing07 Immutability & copies08 The SOLID principles09 Dependency inversion & DI10 SOLID in real code
The model An object keeps its state private and changes it only through its own methods. So the class checks its rules in one place. Callers depend on a contract , not a class. At runtime the object's own class picks the method, so a new type plugs in without editing the callers. Inheritance gives reuse plus a promise that the subclass works wherever its parent does. For reuse alone, use composition .The compiler picks an overload from the declared types. The runtime picks an override from the actual object. In dependency inversion , high-level code owns the interface and the details implement it. Injection hands them in, so tests can pass fakes.
Objects & the four pillars what an object is, and the four ideas OOP rests on The four pillars Define encapsulation Data stays private. Only its own methods change it.
Define abstraction Callers see what an object does, never how it does it.
Define inheritance One class builds on another and can stand in for it.
Define polymorphism The same call runs each object's own version.
Tip Encapsulation hides state and abstraction hides steps.
OOP, procedural or functional Tell OOP from procedural code Procedural code passes data to functions. OOP keeps it in objects.
Tell OOP from functional code OOP hides mutable state in objects. FP keeps data immutable.
Tip Pick by what grows. Objects make new types easy, and functions make new operations easy.
Classes, objects and constructors Tell a class from an object A class is the blueprint. Each new builds an object from it.
Name the kinds of constructor Default, parameterized and copy. If you write none, Java adds one.
Release a file at a known time try (var r = new FileReader(f)) C# has using and Python has with.
Trap Don't release files in a finalizer. The collector may run it late or never. A C++ destructor runs at a known point, like the end of a scope.
Pass an object to a method Say how Java, Python and JS pass objects By value, and the value is a reference. A mutation reaches the caller, a reassignment doesn't.
Tip C++ references and C# ref pass the variable itself, so a reassignment reaches the caller.
Encapsulation & abstraction hide state behind methods, and steps behind names Hide state behind methods Stop callers breaking a rule private long balance; Change it only in methods that check the rule, like withdraw().
Recall Java's access levels private is the class, default the package, protected adds subclasses.
Return a list without leaking it return List.copyOf(items);
Trap A getter and setter per field is a public field with extra typing. deposit(x) keeps the rule inside.
Abstraction or encapsulation Tell abstraction from encapsulation Abstraction picks what to show. Encapsulation enforces the hiding.
Give a real-world example of each A car pedal is abstraction. An ATM guarding your balance is encapsulation.
Build an abstraction Interfaces, abstract classes and well-named methods.
Tip If callers rely on details you meant to hide, the abstraction is wrong. If they change your state directly, the encapsulation is weak.
Trap A wrong abstraction costs more than none. Duplicated code is easier to fix than a bad contract.
Inheritance & interfaces share code or share a contract, and where each stops Inheritance shapes and the diamond Name the shapes of inheritance Single, multilevel, hierarchical and multiple.
Explain the diamond problem Two parents override one ancestor's method. Which wins?
Keep one copy of the ancestor in C++ class B : virtual public A
See the order Python searches D.__mro__ C3 linearisation fixes one order.
Settle clashing default methods in Java B.super.hello(); The class must override it.
Tip Take a parent's contract, not its code. Then the parent's next change can't break you.
Abstract class or interface Share code and state abstract class Shape Fields, constructors and finished methods. Extend only one.
Share only a contract interface Shape Implement many. Default methods are fine, instance fields aren't.
Explain why there's only one base class Merging two parents' fields and constructors has no right answer.
Tip Start a public hierarchy from an interface. An abstract root spends each implementer's one superclass.
Polymorphism & overriding which method runs, and who decides Kinds of polymorphism Run a subclass's version through a base type Subtype polymorphism, picked at runtime.
Reuse one name with other parameters Ad-hoc polymorphism, picked at compile time.
Write one class for every element type class Box<T> { T value; } Parametric polymorphism.
Accept any object with the right method Duck typing, in dynamic languages like Python.
Tip Polymorphism costs indirection. A call site no longer tells you which method runs.
Virtual functions in C++ Let a subclass replace a method virtual double area(); Java methods are virtual already.
Force every subclass to implement it virtual double area() = 0; It makes the class abstract.
Tip A virtual call goes through a vtable, a per-class table of function pointers. That's one extra lookup per call.
Trap Without a virtual destructor, deleting through a base pointer is undefined behaviour.
Overload or override void feed(Animal a) { } void feed(Dog d) { } Animal pet = new Dog(); feed(pet); runs feed(Animal), not feed(Dog)
Tell overloading from overriding Overloads change the parameters. Overrides keep the signature.
Write a valid overload Vary the parameters' number, types or order, not the return type.
Return a narrower type from an override Dog copy() { return new Dog(); } Allowed. Callers skip the cast.
Catch an override that overrides nothing @Override
Trap Change a parameter type and you've written an overload. The base version still runs.
What a subclass can't override Override a private method You can't. The subclass gets a new method the base never calls.
Override a static method You can't. A matching static hides it, and the declared type decides.
Stop subclasses overriding a method public final void pay() C# uses sealed.
Call a static method Parent.greet(); Name the class, never an instance.
Tip Constructors are never inherited, so there's nothing to override.
Trap Java runs p.greet() even when p is null, because it ignores the instance. C# won't compile it.
Composition & coupling has-a over is-a, and classes that know little of each other Composition or inheritance Tell composition from inheritance A car has an engine. An electric car is a car.
Pick inheritance Only when the subtype is truly substitutable.
Count what composition costs Hand-written delegation, more objects, deeper stack traces.
Add a few ready-made methods to a class class Doc(JsonMixin, Base): A mixin, shown in Python.
Tip You can swap a composed part at runtime. A parent is fixed when you write the code.
Trap A subclass inherits the parent's whole public API, wanted or not. You can't take a method back.
The fragile base class Explain the fragile base class problem Editing the base breaks subclasses that relied on its internals.
Make a base class safe to extend Document self-calls, or make them final.
Trap Override add and addAll to count inserts. If the base's addAll calls add, every item counts twice.
Association, aggregation, composition Spot association Objects only use each other, like teacher and student.
Spot aggregation The parts can outlive the whole, like a team's players.
Spot composition The whole owns its parts. Delete a house and its rooms go.
Tip In code, a composite builds its own parts. An aggregate receives them from outside.
Coupling and the Law of Demeter order.customer().address().city(); knows three classes order.shippingCity(); asks the order
Tell coupling from cohesion Coupling is how much modules depend on each other. Cohesion is how focused one module is.
Loosen two classes that know too much Move each decision next to its data. Depend on a small interface.
State the Law of Demeter Talk to your own object, fields, parameters and what you create.
Trap Applied rigidly, the Law of Demeter fills classes with wrapper methods that only pass calls along.
Equality & hashing when two objects count as the same Reference or value equality Check two variables hold the same object a == b In Java. Python uses a is b.
Check two objects hold the same content a.equals(b) Python uses ==. A class needs its own equals for this.
Trap Interned strings make == pass in tests. It fails once a string comes from a file or the network.
equals and hashCode Set<Point> seen = new HashSet<>(); seen.add(new Point(1, 2)); seen.contains(new Point(1, 2)); false without hashCode
Override equals Override hashCode too, from the same fields.
Know which way the contract runs Equal objects must share a hash. Unequal ones may share one too.
List what equals must guarantee Reflexive, symmetric, transitive, consistent, and false for null.
Trap Keep mutable fields out of both. An object whose hash changes inside a set is lost.
Equality with subclasses, ids and sorting Let subclasses pass the type check o instanceof Point p Breaks symmetry once a subclass adds a field.
Require the exact class getClass() == o.getClass() Breaks with proxies and mocks.
Put an entity's id in equals Only if it exists at construction. Use a UUID or a business key.
Let equals and compareTo disagree A HashSet keeps BigDecimal 1.0 and 1.00. A TreeSet keeps one.
Tip Make the class final, or make equals final in the base and compare fixed fields.
Trap A database id is null before save, so new objects look equal. After save the hash changes.
Immutability & copies objects that never change, and safe copies Make a class immutable Set every field once private final int x; Assign it in the constructor. Make the class final too.
Store a mutable input safely this.tags = List.copyOf(tags); Copy first, then validate.
Trap final fields alone are shallow. A final reference to a mutable list still lets callers change the list.
Shallow or deep copy Make a shallow copy in Python copy.copy(order) Shares the nested objects.
Make a deep copy in Python copy.deepcopy(order) Copies everything the fields reach.
Deep-copy a Java object clone() is shallow. Override it, or write a copy constructor.
Tip Shallow is enough when the nested objects are immutable, like strings.
Trap A shallow copy of a list of mutable items still shares the items. Copy them too.
Immutability for threads and map keys Share an object across threads with no locks Make it deeply immutable and publish it safely.
Swap a new value into a shared field Still a race. Guard the field.
Pick a hash map key type An immutable one. Its hash never changes, so it can be cached.
Trap A key mutated after insert hashes to the wrong bucket. The entry stays, but nothing can find or remove it.
The SOLID principles what each letter asks, and how to apply it SOLID in one line each Recall S, single responsibility A class has one reason to change, so a change touches one file.
Recall O, open/closed Add behaviour without editing code that already works.
Recall L, Liskov substitution A subtype works anywhere its base type does, with no surprise throws.
Recall I, interface segregation Small contracts beat one fat one, so nobody writes empty stubs.
Recall D, dependency inversion Depend on abstractions, so logic runs without a real database.
Tip SOLID keeps each change in one place, and lets a test swap in fakes.
Trap Applied blindly, SOLID gives you a class per line of logic.
Single responsibility Define a reason to change A person or group who can ask for different behaviour.
Test a class for SRP quickly Describe it. If you need the word "and", it has two jobs.
Tell SRP from ISP SRP limits what a class does. ISP limits what clients depend on.
Tip Stop splitting when the reasons to change no longer overlap. Aim for cohesion, not small classes.
Trap SRP isn't "do one thing". It asks that a class have one reason to change.
Split a class with too many jobs Split a UserRegistration class A validator, a hasher, a repository and a mailer, one per owning team.
Say what goes wrong months later Tests need a database and a clock. Teams collide in one file.
Tip The original class keeps only the order of the steps, and takes the four parts in its constructor.
Open/closed Add a format without editing the exporter An Exporter interface with one class per format.
Name patterns that support open/closed Strategy, Template Method, Observer, Factory and Decorator.
Balance open/closed with YAGNI Start simple. Add the extension point once the variation is real.
Tip Open for extension doesn't mean zero edits. The edit lands in the wiring, not the business logic.
Trap When providers differ in shape, the interface fills with optional methods. A switch is clearer then.
Liskov substitution Check a subclass against its parent Accept at least as much, promise at least as much, keep its invariants.
Explain the square and rectangle problem A Square ties width to height. Code that sets them apart breaks.
Spot a violation in existing code Empty or throwing overrides, and instanceof checks before calls.
Fix a read-only list that extends a mutable one Split the base into a readable type and a mutable one that adds writes.
Trap Throwing UnsupportedOperationException breaks the contract. It moves a design error to runtime.
Interface segregation Fix a 10-method interface when a class needs 2 Pull out a 2-method interface, and let the wide one extend it.
Fix it when you don't own the interface An adapter implements all ten and forwards the two you use.
Link small interfaces to coupling and cohesion Small interfaces raise cohesion and cut what each client depends on.
Trap A fat interface forces stubs for methods a class never calls. Each stub turns a compile-time gap into a runtime failure.
Dependency inversion & DI depend on interfaces, and hand objects their parts Dependency inversion Invert an OrderService that imports a vendor SDK The order module owns a PaymentGateway. An adapter wraps the SDK.
Tell DIP from DI DIP is the rule and DI the usual tool. Injecting a concrete class isn't DIP.
Apply DIP without a container Take interfaces in constructors. Build the real classes in main.
Trap An interface that mirrors one class method for method inverts nothing. Make it narrower.
Inject a dependency Say what dependency injection is An object gets its collaborators from outside, not by building them.
Say what injection buys you Fakes in tests, cheap swaps, and dependencies you can see.
Pass a required dependency Constructor injection, the default. The object is never half-built.
Pass an optional dependency Setter injection. Nothing forces the call, so watch for nulls.
Pass a dependency that changes per call Method injection. Pass it to the one method that needs it.
Tip Sources disagree on the third form. Some say method injection, others interface injection.
Containers and inversion of control Say what a DI container does It builds the object graph, manages lifetimes and disposes objects.
Tell inversion of control from DI IoC means the framework calls your code. DI is one kind of it.
Tip For a small app, skip the container. Wire everything by hand in one startup function.
Trap A container turns wiring mistakes into startup or first-request failures, not compile errors.
When injection costs too much Handle a stable, pure helper Build it inline. A date formatter needs no test seam.
Read a constructor with eight dependencies One class doing eight jobs. Split it.
Know where heavy abstraction isn't worth it Scripts, prototypes and hot paths.
Compare a service locator with DI The class pulls from a global registry, so its needs stay hidden.
Trap A missing locator registration fails only when that path first runs. Tests must reset a global.
SOLID in real code spot violations and refactor, for expert interviews Spot a SOLID violation Judge a class that fetches, computes and formats It breaks SRP, DIP and open/closed. Split fetch, compute and render.
Judge a method that switches over a type code It breaks open/closed and DIP. Use a class per variant or a handler map.
Find violations with metrics Big classes, type checks, fat interfaces, concrete dependencies.
Tip Keep the switch when the variants are fixed and only the operations grow.
Trap A type switch is rarely alone. A new variant must reach every copy, and a missed one fails at runtime.
Refactor toward SOLID Bring SOLID into a legacy codebase Add characterization tests, then refactor where code changes most.
Order the legacy work SRP first, then DIP at external boundaries, then the rest.
Refactor a god class Put each job behind an interface. A thin class calls them.
Settle two principles that clash By context. SRP adds objects, and early open/closed breaks YAGNI.
SOLID at scale Apply SOLID to microservices A service is the class and its API the interface. One business job each.
Balance SOLID with performance Profile first. Relax SOLID only on a proven hot path.
Nothing matches. Try a shorter word, or clear the search.
Practice Guided practice One question at a time, with the ones you miss coming back.
Practice 90 interview questions Full answers, from beginner to expert.
Found this useful? Pass it on.
Share on LinkedIn
Share on X
Copy link
This sheet stays free. With Pro , you can:
Every answer on this sheet. Read the full answer to all 85 questions it links, not just the 9 free ones.
My sheet. The cards you star and the ones you miss in Quiz me, from every sheet, on one page to quiz and print.
PDFs. Download this sheet and My sheet, laid out for A4, with every question a link to its answer.
The rest of Pro. Every answer in the question library, and 1,000 AI credits a month.