OOP Interview Questions: Trace Dispatch, State and Coupling
Trace one Wallet object through aliases and overridden calls, then use the same model to reason about invariants, substitutability and dependency design.
KnowledgeGate Team
Exam prep & CS education

Many candidates can recite the four OOP pillars. The harder follow-up is to predict which method runs, which object changes, and what created a dependency. References, object state and contracts determine method selection and aliasing across Java, C++ and Python. The Placement Preparation Courses for IT Jobs hub puts this trace alongside broader interview practice.
Read an OOP question as references, objects and contracts
Before tracing code, write three columns: declared or static type, runtime object type, and current object state. Declared type controls which members the compiler lets you call. Runtime type selects an overridden instance method. State records changing field values.
Identity is different from state. Two variables can name the same object, while two objects with equal-looking fields can have different identities. A compact sketch makes this visible:
a -> W1
b -> W1
W1.runtimeType = RewardWallet
W1.balance = 40Here, a and b alias W1. Encapsulation controls its private balance, inheritance makes RewardWallet a subtype of Wallet, and dynamic dispatch selects the override. For a foundation refresher, read OOP for Teaching CS Exams: Classes and Inheritance.
Fully worked trace: which method runs and what prints?
Consider this Java-like model:
class Wallet {
private int balance;
Wallet(int b) { balance = b; }
void add(int x) { balance += x; }
int balance() { return balance; }
}
class RewardWallet extends Wallet {
RewardWallet(int b) { super(b); }
@Override void add(int x) { super.add(x + 2); }
}
void credit(Wallet w) { w.add(10); }
Wallet a = new RewardWallet(40);
Wallet b = a;
credit(a);
b.add(5);
print(a.balance(), a == b);Initially, both variables refer to W1, a RewardWallet with balance 40. credit(a) copies the reference into w, which still points to W1. Dispatch selects RewardWallet.add(10). It calls Wallet.add(10 + 2), so the change is +12 and balance becomes 40 + 12 = 52.
Next, b.add(5) reaches the same object and selects RewardWallet.add(5). The override passes 5 + 2 = 7 to the base method, giving 52 + 7 = 59. Both names still identify W1, so a == b is true.
Statement | Selected method | Delta |
|
|---|---|---|---|
Initial | None | None | 40 |
|
| +12 | 52 |
|
| +7 | 59 |
| 0 | 59 |
The output is 59 true. Type Wallet restricts visible members at compile time, but runtime type RewardWallet selects the override. Assignment b = a copies a reference, not the object.

Encapsulated state is an invariant, not a private keyword quiz
Suppose Wallet adds withdraw(int x). It rejects when x <= 0 || x > balance; otherwise, it subtracts x. Start with a separate W2 at 40. withdraw(50) fails because 50 > 40 and leaves 40. Then withdraw(15) succeeds, producing 40 - 15 = 25.
The private field channels changes through that rule. A public balance = -10 creates a forbidden state. A getter can safely report a value, while an unrestricted setter can break the invariant. Return an immutable view or defensive copy when callers should not mutate an internal collection. This identity-versus-mutability distinction also explains why Java string aliases differ from mutable wallet aliases.
Inheritance cost: substitutability before reuse
Now start a base Wallet at 80. Its withdraw(30) accepts the operation and leaves 80 - 30 = 50. A subclass LockedWallet overrides the method to reject every withdrawal while balance is below 100. A function payThirty(Wallet w) calls w.withdraw(30). It succeeds for Wallet(80) but rejects for LockedWallet(80).
The subclass strengthened a precondition despite the shared base contract, so it is not safely substitutable here. Inheritance is not always bad. It becomes costly when a subtype cannot honour its parent's promises, or a base change forces unrelated subclasses to change.
Composition gives a cleaner boundary. A WithdrawalPolicy decides whether 30 may be withdrawn, while Wallet owns its balance invariant. The policy can vary without making a subtype refuse a valid base operation.
Coupling question: change the dependency, not just the class names
In the coupled design, PaymentService.pay(500) constructs new EmailNotifier() and calls email.send("paid 500"). Adding SMS requires editing PaymentService.
Instead, define Notifier { send(String message); } and inject it through PaymentService(Notifier n). Payment calls only n.send("paid 500"). Because EmailNotifier and SmsNotifier share that contract, switching the constructed collaborator requires zero PaymentService edits here.
Constructor injection reduces knowledge of concrete notification classes. Separating payment work from message delivery keeps each unit cohesive. The trade-off is interface and injection indirection, so use it at a real variation boundary rather than for every helper.
That is the narrow coupling question here: identify the concrete dependency and replace it with a contract. The earlier OOP Design Scenarios: Composition, Interfaces and Abstract Classes post owns the broader design decision, including alert-channel and report-export scenarios, while this trace connects coupling back to dispatch, state and substitutability.

Translate the reasoning across Java, C++ and Python
The reasoning transfers, but the language rules are not identical.
Language | Dispatch and identity micro-check |
|---|---|
Java | Overridden instance methods dispatch dynamically, but fields do not. With initial |
C++ | Declare |
Python | Method lookup is dynamic, so |
Without virtual, the C++ dispatch claim fails. Wallet a = RewardWallet(40) also slices the object into a separate base value. Java uses references, C++ distinguishes values, pointers and references, and Python binds names. Practise these distinctions in the Java Course: Concepts, MCQs & Coding Questions.
How interviewers turn one trace into follow-up questions
One practice sequence is: predict the output, identify declared and runtime types, explain why both names see 59, protect balance, diagnose LockedWallet, reduce notifier coupling, and state a trade-off.
Use this 60-second answer frame: result -> dispatch rule -> state/identity trace -> design consequence -> alternative and trade-off.
Applied here: “The result is 59 true; both variables refer to W1; both calls dispatch to RewardWallet.add; private mutation keeps the invariant inside Wallet; policy composition is safer than a subtype that refuses a valid base operation.”
Short version and the next practice step
Draw aliases before tracing calls.
Separate declared type from runtime type.
Trace the state of the one shared object.
Test whether a subclass honours the base contract.
Name the dependency that should vary.
Your checkpoints are W1: 40 -> 52 -> 59, output 59 true, W2: rejected 50 leaves 40, then successful withdrawal to 25, and notification text "paid 500".
Now rebuild the trace in one language. Change the reward from +2 to +3 and predict the result before running it: credit(a) adds 10 + 3 = 13, b.add(5) adds 5 + 3 = 8, and the final balance is 40 + 13 + 8 = 61. Then deliver the explanation once using the 60-second frame.
For structured follow-through, the Interview & Resume Preparation Course covers resume building, technical and HR interview training, one-to-one resume review and mock-interview support.
Keep learning

Placement Mock Analysis: One Error Ledger Across Every Test Round
Use one error ledger without flattening unlike round results. This worked example shows how to find the first wrong step, prioritise repairs and close errors only after fresh retests.

Internship to PPO: Build a Weekly Evidence Trail Before the Final Review
Use a weekly outcome ledger to make your internship work visible before the final review. This practice model shows how to record delivery, feedback, effect and handoff honestly.

DSA Mock Interview Rubric: A 100-Point Scorecard for Reasoning, Code and Communication
A practical six-part scorecard for running comparable DSA mocks, grading visible evidence and turning weak areas into the next week's practice.

Campus Recruitment Timeline: Stage by Stage from Pre-Placement Talk to Written Offer
Follow a campus drive without guessing. Build an evidence sheet, verify eligibility, plan each preparation window and check the written offer before responding.