Some classes are born to be extended — never to be built.
Class 10 gave every class a family. Today a strange thing happens: we meet a base class that refuses to be built directly — and Java gives us a keyword to make that refusal official. Then we go one step further: a class that is nothing but promises. Small examples first, always; the big files only after the idea already feels easy.
The hook, before anything else: in Class 10, new DeliveryPartner() was perfectly normal. Today the food app's designers say something surprising — "a plain 'delivery partner' should never exist on its own; only bike partners, cycle partners, walkers…". Java can enforce that sentence with one keyword. Finding the bug that makes the keyword necessary is our first stop.
PART 2 · WHAT TODAY DELIVERS
Two refusals. Four notebook drills. One contract.
abstract vs interface.
BY THE END YOU CAN
- Designan abstract class with one abstract method for a real product — and defend why it must stay abstract.
- Classifysix real design scenarios into abstract class or interface — the decision interviewers actually test.
- Debugthe two compile errors this topic produces first:
newon an abstract class, and an interface method with a body. - Explainthe interface-vs-abstract table from memory — row by row, with a reason per row, not a chant.
WHERE THIS SITS
TODAY'S ROUTE · 14 STOPS
- A ₹0-salary bug — the class that should never have been builtDISCOVERY
abstractclass — micro examples first, then the refusalCODE- Abstract METHOD — a heading with no body, overriding made compulsoryCODE
- Abstract class vs plain superclass — when to reach for whichSELF-STUDY
- Worked build — the Part-E spine, typed liveCODE
- Activity 1 — design your own abstract SubscriptionPlanNOTEBOOK
- Activity 2 — why does
new SubscriptionPlan()refuse?NOTEBOOK - Interface — a class that is NOTHING but promisesDISCOVERY
- Interface vs abstract class — THE tableCORE
- Java-8 default/static methods — a 3-line preview, core at C16SELF-STUDY
- One class, MANY contracts — the hat sim + a legal commaSIM
- Payday — one queue pays three different familiesCODE
- Activity 3 — the interface method that brought a bodyNOTEBOOK
- Activity 4 — six scenarios, six verdicts + recapNOTEBOOK
CLASS 11 OF 60 · 18 PAGES · 16 CORE + 2 SELF-STUDY · SELF-STUDY CARDS ARE MARKED WHERE THEY LAND
PART 3 · A CLASS THAT SHOULD NEVER BE BUILT
Some words name real things. Some name only ideas.
Before any Java — a two-word warm-up. You can watch a reel — one specific 30-second clip that actually exists. You cannot watch "content" — not any particular clip, just… content. "Content" is a real and useful idea, but nothing on your feed is only content. Watch what happens when Java lets us build the idea anyway.
MICRO PAIR · SAME THREE LINES, OPPOSITE MEANING — WHICH new IS HONEST?
Java said YES to both. Reality says yes to only one. That gap is today's first bug.
Now the same gap inside the food app: the designers ruled that a "plain" delivery partner must never exist — only bike partners, cycle partners, walkers. A new intern didn't get the memo, typed new DeliveryPartner(), and payroll ran. Predict the payout line before the terminal shows it.
class DeliveryPartner{ String name = "unassigned"; double baseRate = 0.0; // a plain partner has no vehicle, so no rate double calculatePayout() { return baseRate; }}public class ZeroSalary{ public static void main(String[] args) { DeliveryPartner ghost = new DeliveryPartner(); // the intern's line System.out.println("Weekly payout: Rs. " + ghost.calculatePayout()); }}DeliveryPartner; we want Java to refuse that one line for us, forever.
THE MOMENT OF NEED — ONE WORD MAKES THE REFUSAL OFFICIAL
Java's keyword for "this class is an idea, not a thing" is abstract. One word, added in front of class — nothing else in the file changes:
RECOMPILE — AND NOW THE COMPILER FIGHTS FOR US:
ZeroSalary.java:16: error: DeliveryPartner is abstract; cannot be instantiated DeliveryPartner ghost = new DeliveryPartner(); ^
The intern's line is now impossible to compile. The ₹0.0 salary can never happen again — not because everyone remembered the memo, but because the language enforces it.
An abstract class is a class declared with the abstract keyword that cannot be instantiated (new on it is a compile-time error) and exists to be extended by subclasses. It may contain everything an ordinary class contains — fields, constructors, fully implemented (concrete) methods — and it may additionally declare abstract methods (headings without bodies). Any class that inherits an abstract method and does not implement it must itself be declared abstract; the first subclass that implements them all becomes concrete and instantiable.
new on an abstract class is a COMPILE error — the exact sentence the compiler printed. This is the definition; you just watched it earn its keep.
extends works exactly as in C10. Children of an abstract class are built with new as usual — only the parent itself refuses.
An abstract class is NOT empty. name, baseRate and full method bodies all stay — shared by every child, written once.
DeliveryPartner p = new BikePartner(); stays legal — C10's dispatch still works. Only new DeliveryPartner() died.
PART 4 · THE METHOD THAT REFUSES TO HAVE A BODY
Sometimes the parent knows WHAT — never HOW.
The abstract DeliveryPartner still carries a problem: its calculatePayout() returns a made-up 0.0, because a plain partner honestly has no idea how payouts work — bikes earn per km, walkers per order. The parent knows every child must have this method. It just cannot write the body. Java has a shape for exactly that. Two tiny stories first.
An abstract method is a method declared with the abstract keyword that has a signature but NO body — the declaration ends in a semicolon instead of braces: abstract double calculatePayout();. It may appear only inside an abstract class (or an interface). It forces a contract: every concrete subclass MUST override it with a real body, or that subclass must itself be declared abstract. The parent states WHAT must exist; each child supplies HOW.
MICRO PAIR · TWO EVERYDAY STORIES — THE PROMISE, THEN THE PROMISE LIVING NEXT TO REAL CODE
showXP() is written ONCE and already calls xpEarned() — a method that doesn't exist yet! It trusts every future child (RankedMode, CasualMode) to keep the promise. This is the whole power move.But what makes the promise BINDING? A promise nobody enforces is just a comment. Let's try to cheat: write a child of Notification that quietly "forgets" to write ping() — and see who catches us.
javac Forgetful.java —
Forgetful.java:6: error: MutedApp is not abstract and does not override abstract method ping() in Notification class MutedApp extends Notification ^
Read the error slowly — it offers the only two legal escapes: override the method, or declare yourself abstract too (pass the promise down to YOUR children). Staying concrete and silent is not on the menu.
THE FIVE RULES — EACH ONE YOU HAVE NOW SEEN HAPPEN
| RULE | WHAT IT SAYS | WHERE YOU SAW IT |
|---|---|---|
| No body | An abstract method is a signature ending in ; — braces are a compile error. | Micro 3, the hot line |
| Abstract home only | One abstract method forces the whole class to be declared abstract. | Both micros — parents carry the keyword |
| Override is compulsory | Every concrete child MUST override every inherited abstract method. | The MutedApp refusal |
| Or stay abstract | A child that doesn't override must itself be abstract — the promise rolls downhill. | Named inside the error message |
| Mixing is allowed | Abstract and normal methods, plus fields, live together in one abstract class. | Micro 4 — xpEarned() + showXP() |
FALSE — and Micro 4 is your proof: showXP() has a full body inside abstract GameMode. The true statement points the other way: a class holding even ONE abstract method must be abstract. Examiners love swapping that direction.
PART 5 · SELF-STUDY CARD — READ ONCE AT HOME, 4 MINUTES
When do I make the parent abstract at all?
C10's DeliveryPartner was a plain superclass and life was fine. Today it became abstract and life got safer. Both are legal designs — so which do you reach for? One honest question decides it.
KEEP THE PARENT PLAIN WHEN…
new Parent() makes sense
A plain Vehicle in a parking app is fine if generic "vehicle" records really exist. The parent is a complete thing that children merely extend. C10's world.
MAKE THE PARENT ABSTRACT WHEN…
new Parent() would be a lie
Nothing in reality is only "content", only a game mode, only a plain delivery partner. The parent is a shared idea — real code + real fields, but no honest stand-alone object.
The one-question test: "Could a row in my database honestly be JUST the parent?" If no — abstract.
PremiumUser extends User and FreeUser extends User — and every account is always one or the other, never "just a User". Should User be abstract? (Yes — no honest stand-alone object exists. If someday "plain accounts" become real, the design flips back.)
DON'T TRUST THE PARENTHESES — SETTLE THE SELF-CHECK WITH A RUNNING FILE:
C:\...\class-11> javac UserCheck.java
(clean — every account is a real child)
C:\...\class-11> java UserCheck
@zoya_edits holds the Premium plan
@rohan.lofi holds the Free plan
PART 6 · WORKED EXAMPLE — EVERYTHING SO FAR, ONE HONEST FILE
The spine: one idea, two real children, one payroll.
You already own every piece of this file: the abstract parent (Part 3), the abstract method + compulsory override (Part 4), and C10's dispatch. Nothing new is introduced here — that is the point of a worked build. Assemble it floor by floor.
THE ASSEMBLY PLAN — ONE PIECE PER PRESS · REAL UML, EVERY EDGE ACTUALLY DRAWN
Both children hang off ONE drawn edge into the hollow triangle — the UML way of writing "IS-A". Same question — "your payout?" — two honest answers. The parent never had to guess.
abstract class DeliveryPartner{ String name; int deliveries; void goOnDuty() { System.out.println(name + " is on duty"); } abstract double calculatePayout(); // the promise}class TopRatedDeliveryPartner extends DeliveryPartner{ TopRatedDeliveryPartner(String partnerName, int done) { name = partnerName; // inherited field, plainly assigned deliveries = done; } double calculatePayout() // promise kept { return deliveries * 45.0; }}class BikePartner extends DeliveryPartner{ BikePartner(String partnerName, int done) { name = partnerName; deliveries = done; } double calculatePayout() // promise kept — its own way { return deliveries * 32.0; }}public class Spine11{ public static void main(String[] args) { DeliveryPartner meera = new TopRatedDeliveryPartner("Meera", 10); DeliveryPartner arjun = new BikePartner("Arjun", 10); meera.goOnDuty(); arjun.goOnDuty(); System.out.println("Meera earns Rs. " + meera.calculatePayout()); System.out.println("Arjun earns Rs. " + arjun.calculatePayout()); }}this, no super. The constructor parameter is named partnerName, so the inherited field name is assigned plainly — no name clash, no ceremony. Reach for those keywords only when a real clash or a parent constructor genuinely demands them (C10 showed the demanding cases).
PART 7 · ACTIVITY 1 — NOTEBOOKS OUT · DESIGN, NO CODE
Your own OTT subscription is an abstract class in disguise.
THE SCENE Spotify Student. Netflix Mobile. Prime Student. Every plan you actually pay for is a specific plan — nobody on earth subscribes to "a plan" in general. Sound familiar? That is exactly the Content/Reel gap from Part 3.
YOUR TASK In your notebook — signatures and sentences only, no method bodies:
- Write the class heading for an abstract class named
SubscriptionPlan. - Give it ONE field every plan genuinely shares (pick your own — think of what appears on every bill).
- Write the heading of ONE abstract method
renewalPrice()that returns adouble— remember how an abstract method ends. - Write the class heading of ONE concrete child, named after a real plan you or a friend pays for.
- Finish with one sentence: why must
SubscriptionPlanstay abstract?
Attempt all five in the notebook first — the sheet stays locked until you do.
TYPE IT, COMPILE IT, RUN IT — THE DESIGN MUST SURVIVE A REAL TERMINAL:
C:\...\class-11> javac PlanCheck.java
(clean — the child kept the promise)
C:\...\class-11> java PlanCheck
Aarav pays Rs. 59.0
- MARK 1
abstractsits beforeclass— position matters, it is part of the heading. - MARK 2
abstract double renewalPrice();— the semicolon IS the "no body" syntax. Braces here would be a compile error. - MARK 3The why-sentence full-marks shape: "No customer ever holds a plain SubscriptionPlan — only specific plans exist, so building the idea directly must be forbidden."
- WHY THE BODYYour notebook answer carries headings only — but the sheet ships the COMPILING version, because a concrete
SpotifyStudentwithoutrenewalPrice()refuses to compile (Part 4's rule). A solution that cannot run is an idea, not a solution.
PART 8 · ACTIVITY 2 — ERROR DETECTION · READ LIKE A COMPILER
A teammate "just wants a quick test object."
THE SCENE Your Activity-1 design got merged. A teammate writing a quick test types this and hits compile:
YOUR TASK In the notebook, answer each on its own line:
- Which line refuses to compile — and quote the compiler's exact key phrase from memory.
- Explain WHY Java must refuse, in one sentence that mentions
renewalPrice(). - Fix the test WITHOUT touching
SubscriptionPlanitself — what is the one-line change? - Bonus: is the left side of the assignment (
SubscriptionPlan p) also illegal? Careful…
Four written answers first. The bonus catches half the room.
- Q1The hot line. Key phrase:
SubscriptionPlan is abstract; cannot be instantiated— the same sentence ZeroSalary produced in Part 3. - Q2Full-marks shape: "If Java built the object,
p.renewalPrice()would have NO body to run — the class only promises the method, it never wrote it." The refusal protects the very next line. - Q3Build a real child instead:
SubscriptionPlan p = new SpotifyStudent();— one line, the parent file untouched. - BONUSThe left side is perfectly legal. An abstract type as a REFERENCE is normal and useful — that is how Spine11's
meeraandarjunwere declared. Onlynew SubscriptionPlan()— the right side — is the crime.
PROOF 1 — THE MERGED FILE EXACTLY AS THE TEAMMATE COMPILED IT (Activity-1 classes above the test):
QuickTest.java:19: error: SubscriptionPlan is abstract; cannot be instantiated SubscriptionPlan p = new SubscriptionPlan(); ^ 1 error
PROOF 2 — THE ONE-LINE FIX, THEN A REAL RUN (everything else untouched):
C:\...\class-11> javac QuickTest.java
(clean)
C:\...\class-11> java QuickTest
59.0
PART 9 · A PROBLEM extends CANNOT SOLVE
Finance wants ONE promise from three unrelated families.
New requirement lands: "Anything the app pays — delivery partners, restaurant vendors, refunded customers — must expose one uniform method, so payroll can treat them all alike." Three families. No shared parent. Watch both of our existing tools fail before the new one appears.
TWO DEAD-ENDS — WHY YESTERDAY'S TOOLBOX IS NOT ENOUGH
"Make them all extend one abstract Payable class." But Vendor already extends Business, and Java allows exactly ONE parent per class (C10's single-inheritance law). Forcing three unrelated families under one parent would also invent a fake IS-A: a refunded customer IS-A payable-thing? That is a job description, not an identity.
"Just tell everyone to write the same method." A team memo is Part 4's unenforced promise all over again — one renamed method (getPayout() vs payableAmount()) and payroll breaks at 2 a.m. with no compiler on our side. We NEED the enforcement, without demanding a shared parent.
The moment of need: we want a pure contract — a bundle of promises with no fields to inherit, no bodies to share, no parent slot consumed. Java's name for that is interface. A class doesn't extend a contract, it signs it: implements.
An interface is a fully abstract reference type declared with the interface keyword: a named collection of method signatures (all implicitly public abstract) and constants (all implicitly public static final), with no instance fields and no constructors. A class signs the contract with implements and must then provide public bodies for every promised method. Because an interface consumes no parent slot, one class may implement MANY interfaces (comma-separated) while still extending one class — this is how Java delivers what multiple inheritance promised, without the diamond.
MICRO PAIR · THE SMALLEST CONTRACT EVER SIGNED — AND WHAT SIGNING COSTS
interface replaces abstract class; implements replaces extends. The promise-keeping duty is EXACTLY Part 4's rule.public out loud. C10's no-narrowing law, resurfacing.Scale the micro up: the finance contract is Payable with one promise — double payableAmount(). Here it is signed by Vendor, a class from a completely different family. Predict the payout line.
interface Payable{ double payableAmount(); // public + abstract, automatically}class Vendor implements Payable{ int ordersServed = 50; public double payableAmount() // public — Micro 6's lesson { return ordersServed * 250.0; }}public class FirstContract{ public static void main(String[] args) { Payable p = new Vendor(); // contract as reference type! System.out.println("Owed: Rs. " + p.payableAmount()); }}public abstract without writing it. Keepers must write public themselves — narrowing is refused. Everything else you already knew from Part 4.
PART 10 · THE COMPARISON EVERY INTERVIEW ASKS
Two refusals, one table — every row has a reason you watched.
You now hold BOTH tools. Neither can be built with new — but they refuse for different reasons and shine in different jobs. This table is the single most-asked comparison in Java interviews; today every row is a memory, not a memorisation.
| QUESTION | ABSTRACT CLASS | INTERFACE |
|---|---|---|
| Keyword pair | abstract class + extends | interface + implements |
| How many can a class take? | ONE parent — single inheritance | MANY contracts — comma-separated |
| Instance fields? | Yes — name, deliveries lived in Spine11 | No — only public static final constants |
| Method bodies? | Yes — goOnDuty() had one | Classically none (Java-8 note next part) |
| Constructors? | Yes — run via the child's chain | Never — nothing to initialise |
| Default access of methods | Package-private unless stated | public automatically — Micro 6's trap |
| Relationship it models | IS-A — identity ("a bike partner IS a delivery partner") | CAN-DO — capability ("a vendor CAN be paid") |
THE 5-SECOND DECISION — WHICH DO I REACH FOR?
REACH FOR abstract class WHEN…
shared FIELDS or shared BODIES exist
The family owns state and common code — name, deliveries, a ready goOnDuty(). You are building the TRUNK of one family tree.
REACH FOR interface WHEN…
only a PROMISE must cross families
No state, no bodies — just "everyone answers this question". Payable cut across partners, vendors AND customers without touching their parents.
Say it with the IS-A vs CAN-DO row and you have answered the question completely — in two sentences.
PART 11 · SELF-STUDY CARD — A 3-LINE PREVIEW, NOTHING MORE
One asterisk on the table — parked, on purpose.
default or static. (2) This exists so old interfaces can gain new methods without breaking every signer in the world. (3) The full treatment — rules, clashes, when-to-use — is core material at Class 16; nothing before then requires it.
Why we park it: today's mental model — "interface = pure promise" — is the one the exam table and every classification question rely on. Learn the exception AFTER the rule is muscle memory. If it appears in a question bank early, you now know its name and its home.
PART 12 · THE COMMA THAT extends NEVER EARNED
One person. Three hats. All legal.
C10 taught the hard law: ONE parent, ever — class A extends B, C is refused. Contracts play by a friendlier rule, because signing a promise consumes nothing. Watch the same delivery partner put on three hats, one per press.
THE CONTRACT DIAGRAM — ONE HAT PER PRESS, THEN THE INK: DASHED EDGES ARE THE SIGNATURES
Three dashed edges from ONE class — all legal, because dashed means "signed a contract", not "IS-A". Hats are jobs, not identities: you can hold many jobs, you can only be one person.
Micro first — the smallest triple-signing that can exist: before the full file, just the heading and what it owes. Count the debts: three contracts × one promise each = three public methods due.
implements — never after extends. Each contract adds duties, not fields, so no diamond confusion is possible.name WITH state — whose value wins? Java refuses the ambiguity at the parent level, and allows it at the promise level.interface Payable{ double payableAmount();}interface Trackable{ String currentZone();}interface Rateable{ void addStars(int stars);}class Partner implements Payable, Trackable, Rateable{ int deliveries = 10; int totalStars = 0; public double payableAmount() { return deliveries * 45.0; } public String currentZone() { return "Banjara Hills"; } public void addStars(int stars) { totalStars = totalStars + stars; }}public class ThreeHats{ public static void main(String[] args) { Partner ravi = new Partner(); Payable forFinance = ravi; // finance sees ONE hat only Trackable forMaps = ravi; // maps sees another System.out.println("Owed: Rs. " + forFinance.payableAmount()); System.out.println("Zone: " + forMaps.currentZone()); }}ADD-ON · THE HALF-KEPT CONTRACT — WHEN A CLASS CANNOT PAY EVERY DEBT
Can't implement them all yet? Then SAY so: abstract.
ThreeHats paid all three debts in one class. Real sprints are messier — sometimes a module isn't ready and one promise must wait. Java gives you exactly one honest way out, and it is a keyword you already own.
Week one of the food app: the GPS module ships next sprint, so currentZone() simply cannot be written yet. A teammate signs both contracts anyway and pays only one. Predict the compiler's verdict before the terminal shows it.
interface Payable{ double payableAmount();}interface Trackable{ String currentZone();}class WeekOnePartner implements Payable, Trackable{ public double payableAmount() { return 300.0; } // currentZone() NOT written — GPS module lands next sprint}public bodies. Only one arrived. The compiler charges the signature line — the promise — not the missing method.
The honest week-one design: the class declares its unpaid debt with abstract, and the promise rolls forward until a child finally pays it — Part 4's pass-it-down rule, now crossing a contract.
interface Payable{ double payableAmount();}interface Trackable{ String currentZone();}abstract class WeekOnePartner implements Payable, Trackable{ public double payableAmount() { return 300.0; } // currentZone() stays owed — abstract makes the debt official}class GpsPartner extends WeekOnePartner{ public String currentZone() // sprint two: the last debt, paid { return "Madhapur"; }}public class HalfHats{ public static void main(String[] args) { Payable forFinance = new GpsPartner(); Trackable forMaps = new GpsPartner(); System.out.println("Owed: Rs. " + forFinance.payableAmount()); System.out.println("Zone: " + forMaps.currentZone()); }}A class that implements an interface but does not provide bodies for ALL of its methods must itself be declared abstract. The unimplemented promises pass down to its subclasses, and the first subclass that implements every remaining method becomes concrete and instantiable — the same chain rule you learnt for abstract methods in Part 4, now crossing a contract.
ADD-ON · THE DIAMOND PROBLEM — WHY THE COMMA IS SAFE HERE AND POISON AFTER extends
Two parents, one method, whose body wins? Interfaces make the question disappear.
The contrast card above said "no diamond confusion is possible" — now EARN that sentence. First watch the diamond actually refuse with classes, then watch the interface version dissolve it in a real run.
Draw the shape first: ONE grandparent at the top, TWO parents in the middle who both inherit perform(), ONE student at the bottom who inherits from both parents. Top → two sides → bottom: the four boxes form a diamond ◇. The question the shape asks: when the student calls perform(), whose copy travels down — the left parent's or the right parent's?
THE DIAMOND, POSED WITH CLASSES — WHY JAVA SLAMS THIS DOOR
class Performer // the TOP of the diamond{ void perform() { System.out.println("On stage"); }}class Guitarist extends Performer // LEFT side — overrides{ void perform() { System.out.println("Guitar riff"); }}class Dancer extends Performer // RIGHT side — overrides too{ void perform() { System.out.println("Hip-hop steps"); }}class FestStudent extends Guitarist, Dancer // the BOTTOM — whose perform()?{}student.perform() would have no honest answer. Java refuses so hard the comma after extends does not even PARSE — the diamond question can never be asked with classes.THE SAME DIAMOND, REDRAWN WITH INTERFACES — WATCH IT DISSOLVE IN A REAL RUN
Same four boxes, new material: the top is now a contract, the two sides are contracts that extends it (yes — an interface may extend an interface), and the bottom is ONE class signing both sides. The shape is identical. The ambiguity is gone — because contracts carry promises, never bodies: three copies of the same promise merge into ONE debt.
interface Performer // TOP of the diamond — the shared promise{ void perform();}interface MusicClub extends Performer // LEFT side — inherits the promise{ void perform(); // re-states it — still just a promise, NO body}interface DanceClub extends Performer // RIGHT side — inherits it too{ void perform(); // the THIRD copy of the same promise}class FestStudent implements MusicClub, DanceClub // BOTTOM — both sides signed{ public void perform() // ONE body settles ALL THREE copies { System.out.println("Mashup set: guitar + footwork"); }}public class TwoClubs{ public static void main(String[] args) { FestStudent zara = new FestStudent(); MusicClub onStageA = zara; // through the LEFT side DanceClub onStageB = zara; // through the RIGHT side Performer onTop = zara; // even through the TOP onStageA.perform(); onStageB.perform(); onTop.perform(); }}extends (not implements) — and unlike classes, an interface may even extend SEVERAL interfaces. Contracts stack safely at every level, for the same reason: no bodies, no state, no fights.
The diamond problem: a common ancestor at the top, two middle types that each inherit (and override) the same method, and one bottom type inheriting from both — so two implementations (bodies + state) of one method would reach the bottom, and no call could honestly pick one. Java forbids multiple class inheritance outright (the comma after extends does not even parse) and allows the SAME diamond drawn with interfaces, because interfaces contribute only method signatures — no bodies, no instance state. However many paths the promise travels down (top, left, right), the copies merge into a single obligation, and the implementing class's ONE public body satisfies them all — nothing exists to be ambiguous.
PART 13 · WORKED EXAMPLE — THE FINANCE TEAM GETS ITS WISH
One queue. Three families. Zero special cases.
Part 9 opened with finance's demand: pay partners, vendors and refunded customers through one uniform door. Every tool is now in hand. Watch the payoff: a single Payable[] array holds all three families, and one loop pays everyone — payroll never asks "which family are you from?"
interface Payable{ double payableAmount();}class Partner implements Payable{ int deliveries = 10; public double payableAmount() { return deliveries * 45.0; }}class Vendor implements Payable{ int ordersServed = 50; public double payableAmount() { return ordersServed * 250.0; }}class RefundedCustomer implements Payable{ double refundDue = 320.0; public double payableAmount() { return refundDue; }}public class Payday{ public static void main(String[] args) { Payable[] queue = { new Partner(), new Vendor(), new RefundedCustomer() }; double total = 0.0; for (Payable p : queue) { total = total + p.payableAmount(); // no family check, ever } System.out.println("Total paid out: Rs. " + total); }}Pause and look back: Part 3's compiler refused a dishonest object. Part 13's compiler guaranteed that three honest strangers answer one question. Refusal and guarantee are the same power — the type system working for you, before the program ever runs.
PART 14 · ACTIVITY 3 — ERROR DETECTION · READ LIKE A COMPILER
A helpful teammate "improves" the contract.
THE SCENE A teammate on Java 7 tooling decides the Payable contract should "help" its signers by including a ready-made body:
YOUR TASK In the notebook, each answer on its own line:
- Does this compile under classic (pre-Java-8) interface rules? One word, then the reason.
- Predict the compiler's complaint — which part of the method is the problem, the heading or the body?
- Explain to the teammate WHY the language forbids it — use the word "promise" or "contract" in your sentence.
- Bonus: the teammate's
return 0.0;default — where have you seen a "default 0.0" cause real damage today?
Four lines in the notebook before the sheet opens.
- Q1No. Classic interface methods are implicitly
abstract— and an abstract method with a body is a contradiction the compiler rejects. - Q2The BODY. The message reads:
interface abstract methods cannot have body— the heading alone was perfectly legal. - Q3Full-marks shape: "An interface IS the contract, not a worker — the moment it carries working code, signers can silently inherit behaviour nobody promised, and the contract stops being pure."
- BONUSPart 3's ZeroSalary — a "sensible default" of
0.0is exactly the quiet wrong-salary bug that made us reach forabstractin the first place. Defaults that lie are worse than refusals. - HONEST FOOTNOTEJava 8's
defaultkeyword (Part 11's parked card) makes a marked version of this legal — with new rules, taught properly at Class 16. Unmarked bodies remain illegal in every Java.
PROOF 1 — THE TEAMMATE'S FILE EXACTLY AS PUSHED, AND THE COMPILER'S VERDICT:
Payable.java:4: error: interface abstract methods cannot have body double payableAmount() ^ 1 error
PROOF 2 — THE CONTRACT RESTORED + A SIGNER + A RUN, ONE COMPLETE FILE:
C:\...\class-11> javac ContractCheck.java
(clean — the contract is pure again)
C:\...\class-11> java ContractCheck
Owed: Rs. 10000.0
PART 15 · ACTIVITY 4 — THE DESIGNER'S CHAIR · SIX VERDICTS
Abstract class or interface? Six real briefs, you decide.
THE RULE OF THUMB You built it in Part 10 — shared fields/bodies call for an abstract class (IS-A trunk); a promise crossing unrelated families calls for an interface (CAN-DO hat). Write six verdicts in the notebook, each with a one-line reason, BEFORE revealing any answer.
- A payment gateway must support Cards, Net-Banking, and Wallets — each processes a payment completely differently, and they share no stored data.
- Every
SocialMediaPost— text, photo, reel — must carry a timestamp, and thegetTimestamp()logic is IDENTICAL for all of them. - The
Payablepromise must be enforced acrossDeliveryPartner,VendorandCustomer— three families with three different parents. - Your Class-1 flatmate expense register grows up: every tracker variant shares the members list and the add-expense code, but splits the bill differently.
- An
AttendanceCalculatorneeds only ONE thing shared: everyone answerscompute(). No common fields, no common code. - A
Notifierfamily — SMS, email, push — must all send, and the team wants a shared retry counter and shared logging code in one place.
Six verdicts + six reasons in the notebook first. Two of them trap the hasty.
Scenarios 5 and 6 are the same domain with ONE line changed — state and shared code flipped the verdict. That single observation IS the exam answer.
PROOF IN CODE — THE FLIP, AS TWO COMPLETE RUNNING FILES. FIRST, SCENARIO 5 (INTERFACE):
C:\...\class-11> javac AttendanceCheck.java
(clean)
C:\...\class-11> java AttendanceCheck
Theory: 84.0%
Lab: 100.0%
NOW SCENARIO 6 — SAME DOMAIN, BUT A SHARED FIELD + SHARED CODE APPEAR (ABSTRACT CLASS):
C:\...\class-11> javac NotifierCheck.java
(clean)
C:\...\class-11> java NotifierCheck
SMS sent, retries left: 3
Push sent, retries left: 3
PART 16 · WHAT YOU NOW OWN
Two keywords in, the whole design conversation opens.
| YOU CAN NOW… | BECAUSE… | PROOF FILE |
|---|---|---|
| Forbid a dishonest object | abstract class makes new a compile error on the idea | ZeroSalary.java |
| Force a method's existence | an abstract method must be overridden or passed down | the MutedApp refusal |
| Mix promise with real code | abstract + concrete members coexist in one trunk | Spine11.java |
| Cut a promise across families | interface + implements consume no parent slot | FirstContract.java |
| Stack many capabilities | the comma after implements is legal — hats, not identities | ThreeHats.java |
| Pay strangers through one door | a contract-typed array + dispatch = zero special cases | Payday.java |
HOMEWORK — DUE BEFORE CLASS 12
MyPlans.java Turn your Activity-1 notebook design into a running file. Requirements, one per line:
- Type your abstract
SubscriptionPlanwith the field you chose and the abstractrenewalPrice(). - Write TWO concrete plan children from your real life — each keeping the promise with its true monthly price.
- In
main, declare both through aSubscriptionPlanreference — Spine11's pattern. - Print each renewal price, then the total you actually pay per month (brace yourself).
- Add ONE comment line above the class stating why it must stay abstract — your Activity-1 sentence, now living in code.
Open only AFTER your file runs — or refuses in a way you cannot explain.
THE FILE MUST SURVIVE BOTH COMMANDS BEFORE YOU SLEEP:
C:\...\class-11> javac MyPlans.java
(clean — both promises kept)
C:\...\class-11> java MyPlans
Music: Rs. 59.0
Video: Rs. 149.0
Monthly total: Rs. 208.0
- CHECK 1The terminal above is the target SHAPE — your prices will differ; the three-line structure must not.
- CHECK 2No
this, nosuper, no constructors — none were needed. Ceremony only where the design demands it. - CHECK 3Every brace on its own line — including inside the children. The habit IS the deliverable.