Free degree-level programming lessons for careful independent study.

Degree Level Programmes · Programming 2 · Lesson 7

Polymorphism: Cost and Benefit

Use polymorphism to substitute behaviours while understanding the readability, indirection and performance trade-offs.

Lesson Overview

Use polymorphism to substitute behaviours while understanding the readability, indirection and performance trade-offs.

Portfolio focus: Replace a conditional with two implementations of one interface.

ConceptFlexible substitution
Run filePolymorphismCostBenefitDemo.java
BaselineHello
Evidence3 tasks

Starter: think before typing

Before running this flexible substitution example, find the line where the main idea becomes active. Write a prediction: what must already be true for that line to work, and what should be different after it runs? The checked run ends with `Hello`; predict how the focus line helps produce that evidence.

Learning Objectives

  • Call behaviour through a shared type.
  • Explain dynamic dispatch in simple terms.
  • Use polymorphism to remove a brittle conditional.
  • Describe the cost of extra abstraction.

Learning Outcomes

  • By the end of the lesson, you can call behaviour through a shared type.
  • By the end of the lesson, you can explain dynamic dispatch in simple terms.
  • By the end of the lesson, you can use polymorphism to remove a brittle conditional.
  • By the end of the lesson, you can describe the cost of extra abstraction.

Why this idea exists

Polymorphism exists so different implementations can be used through the same kind of reference. The calling code asks for a behaviour, not a particular concrete class.

The idea grew with object-oriented programming and became central to flexible design because it lets programs replace condition-heavy logic with substitutable behaviours.

This lesson fits the arc after inheritance and interfaces because it asks for judgement about cost. Polymorphism can make code easier to extend and test, but too much indirection can make a small program harder to read.

Deep dive

Mechanism in this example

The important mechanism is visible around `Formatter formatter = new PlainTextFormatter();`. Read it as a concrete move in the program, not as decorative syntax: identify what value, object, branch, call or boundary is being created at that point.

Design pressure

This lesson fits the arc after inheritance and interfaces because it asks for judgement about cost. Polymorphism can make code easier to extend and test, but too much indirection can make a small program harder to read.

Failure mode to watch

For Polymorphism: Cost and Benefit, deliberately disturb the assumption behind `Formatter formatter = new PlainTextFormatter();`: use an awkward value, missing input, wrong order of calls or boundary case. The useful question is how that disturbance exposes a weakness in the flexible substitution design.

Extension step

Extend the example by doing this: Trace which implementation is selected during execution. The point is to make one small change that forces you to revisit the concept, rather than adding unrelated features.

Portfolio standard

The portfolio note should not repeat the lesson wording. It should show the edited code, the run result, and your own explanation of this evidence: explain one benefit and one cost of the design.

Lesson visual

Two interchangeable strategy cards plugged into one program socket, with notes for flexibility, indirection and testing cost.
Two interchangeable strategy cards plugged into one program socket, with notes for flexibility, indirection and testing cost.Download visual

Type this and run it

Create PolymorphismCostBenefitDemo.java, type the program, and run it before changing anything. This section is about reproducing the checked baseline.

public class PolymorphismCostBenefitDemo {
  public static void main(String[] args) {
    Formatter formatter = new PlainTextFormatter();
    System.out.println(formatter.format("Hello"));
  }
}

interface Formatter {
  String format(String text);
}

class PlainTextFormatter implements Formatter {
  public String format(String text) {
    return text;
  }
}

Build and run it with:

javac PolymorphismCostBenefitDemo.java && java PolymorphismCostBenefitDemo

Expected baseline: Hello

Run the code in your browser

Use the editor as an experiment surface. First run the checked version, then make one small change to the part of the program that demonstrates flexible substitution and compare the new behaviour with the reference output.

Line-by-line explanation

Read the code as a sequence of responsibilities. The focus line for this lesson is Formatter formatter = new PlainTextFormatter();; the surrounding lines prepare it, use its result or make the behaviour observable.

public class PolymorphismCostBenefitDemo {

This names the runnable class for the Polymorphism: Cost and Benefit example, giving the compiler and JVM one clear unit to build.

public static void main(String[] args) {

This is the program entry point. In Polymorphism: Cost and Benefit, it keeps the demonstration of flexible substitution in one traceable starting script.

Formatter formatter = new PlainTextFormatter();

This introduces formatter as named state for Polymorphism: Cost and Benefit. Later lines can read, update, pass or print that specific value as evidence.

System.out.println(formatter.format("Hello"));

This prints formatter.format("Hello") as the observable evidence for Polymorphism: Cost and Benefit. The output lets the learner check whether the flexible substitution idea behaved as predicted.

}

This closes the innermost Polymorphism: Cost and Benefit block, so the immediately preceding method, branch or loop has finished.

}

This closes the outer Polymorphism: Cost and Benefit structure, returning the reader to the surrounding class or file.

interface Formatter {

This declares the Polymorphism: Cost and Benefit behavioural contract; later code can depend on the capability instead of one fixed implementation.

String format(String text);

This declares format for Polymorphism: Cost and Benefit. The semicolon matters because an interface gives the contract here, not the body.

}

This closing brace number 3 completes another layer of the Polymorphism: Cost and Benefit source structure Java has been checking.

class PlainTextFormatter implements Formatter {

This starts a supporting class so Polymorphism: Cost and Benefit can separate the lesson idea into its own named responsibility.

public String format(String text) {

This starts format, a named Polymorphism: Cost and Benefit operation. Its parameters describe what information comes in; its body decides what work is done.

return text;

This sends a Polymorphism: Cost and Benefit result back to the caller, so the surrounding code can use the answer.

}

This closing brace number 4 completes another layer of the Polymorphism: Cost and Benefit source structure Java has been checking.

}

This closing brace number 5 completes another layer of the Polymorphism: Cost and Benefit source structure Java has been checking.

Worked example

From code to explanation

Problem: Use Polymorphism: Cost and Benefit to complete a small portfolio-quality step: Replace a conditional with two implementations of one interface.

Method: Locate the line `Formatter formatter = new PlainTextFormatter();`, explain the exact role it plays, then decide what you would change to extend the example without changing the whole program.

Reveal worked answer

The checked run should produce `Hello`. A strong answer links the result back to flexible substitution: what was created, selected, stored, called or protected, and why that matters for the portfolio task.

Trace the program

Before: Before the key operation, identify the relevant value, object, branch or resource that the flexible substitution concept depends on.

During: Trace `Formatter formatter = new PlainTextFormatter();` as the Polymorphism: Cost and Benefit example executes. Say whether that operation creates data, checks a condition, calls behaviour, stores information or crosses a boundary.

After: Compare the run with the expected evidence: `Hello`.

Change: Now trace which implementation is selected during execution, run again, and explain the smallest reason the behaviour changed.

Common misconception

A common mistake in polymorphism: cost and benefit is treating the example as a finished answer. For flexible substitution, the important question is narrower: which operation carries the idea, what does it make possible, and what would break if you changed it carelessly?

Quick checks

1. In this Polymorphism: Cost and Benefit example, what is the best reason to focus on `Formatter formatter = new PlainTextFormatter();`?

2. Which evidence is strongest after you edit and rerun this example?

How to study this lesson

For Polymorphism: Cost and Benefit, predict how flexible substitution changes the run before you press Run.

Use the first portfolio task as your main edit: Replace a conditional with two implementations of one interface.

Use the second task as your variation: Trace which implementation is selected during execution.

Finish with evidence, not a diary entry: Explain one benefit and one cost of the design.

Portfolio Practice

  1. Replace a conditional with two implementations of one interface.
  2. Trace which implementation is selected during execution.
  3. Explain one benefit and one cost of the design.

Final self-check

Can you explain the key operation?

Explain the line identified in the quick check in one or two sentences. Your answer should say what it does before the output Hello appears.

Can you justify the portfolio evidence?

Your evidence should include the original run, one edited run, and a short note explaining how the edit affected flexible substitution.

Study route

Practise flexible substitution by predicting the Java example, typing it, running it in the browser, tracing the result and saving portfolio evidence.

Next, move into Collections, Generics and Iteration and carry forward one improvement from this lesson into the next program.