Programming technique · B3.2.3 · Higher level only
Abstraction and abstract classes
Sometimes a superclass describes a useful general role but is too incomplete to represent a sensible object. Abstraction lets the program keep the shared features while requiring concrete subclasses to supply the behaviour that the general class cannot decide.
activity(), so a plain Animal object was valid. Now ask a design question: what if there is no meaningful general Animal activity?Make the general type deliberately incomplete
A weak solution invents a fake default behaviour just so the superclass can be instantiated. An abstract design says something more precise: every concrete Animal must support activity(), but the general Animal class should not decide what that activity is.
activity() to give different polymorphic behaviour, but the parent still supplied a default. Making activity() abstract keeps the same “same method call, different behaviour” idea while forcing every concrete child class to provide its own version. Use this when a generic parent implementation would be meaningless, misleading or easy to forget to replace.Shared in Animal
Name state, construction and label() are genuinely common, so the abstract superclass can implement them once.
Required from subclasses
activity() is part of the common promise, but Dog and Human must each provide the concrete implementation.
Not a valid object
A plain Animal would have an unresolved required behaviour, so the design prevents direct instantiation.
What an abstract class can contain
| Member | Allowed in an abstract class? | Purpose in this model |
|---|---|---|
| Fields / state | Yes | name is shared by every Animal. |
| Constructor / initialiser | Yes | Concrete subclasses still need the parent part of the object initialised. |
| Implemented method | Yes | label() has one shared implementation. |
| Abstract method | Yes | activity() states a required operation without choosing the subtype-specific behaviour. |
| Direct object construction | No | The abstract class represents an incomplete general type. |
Java: abstract class and abstract methods
Java marks the class itself abstract. An abstract method has a signature but no body. A concrete subclass must implement the inherited abstract method, normally using @Override. The abstract superclass may still have fields, a constructor and normal implemented methods.
Python: ABC and @abstractmethod
Python's standard abc module provides explicit abstract-base-class behaviour. Subclass ABC and decorate the required operation with @abstractmethod. A subclass that leaves the required operation abstract cannot be instantiated.
Read the hierarchy as a contract
| Class | Can create objects? | Shared behaviour | Required / concrete activity |
|---|---|---|---|
| Animal {abstract} | No | getName(), label() | activity() is required but unresolved |
| Dog | Yes | inherits shared Animal behaviour | implements Dog activity |
| Human | Yes | inherits shared Animal behaviour | implements Human activity |
In UML, abstract class and operation names are commonly shown in italics. The explicit {abstract} label above makes the meaning visible even when typography is unavailable.
The caller depends on the abstraction
The array is typed as Animal[], but every object inside it is concrete. The caller relies only on operations promised by Animal. Runtime dispatch from T23 still selects each concrete activity() implementation.
Python does not need a declared array element type, but the design principle is the same: the caller works with objects that satisfy the Animal contract and does not need subtype-specific selection.
Clear common contract
Code using Animal knows that every concrete Animal supplies activity(). A subtype cannot silently omit a required operation and still be treated as complete.
Shared code stays shared
Abstract does not mean empty. State and common behaviour can remain in one superclass instead of being duplicated across subclasses.
Caller stays modular
The caller depends on the abstract role rather than the details of Dog, Human or a future subtype. New concrete classes can fit the same structure without rewriting the caller loop.
Use it when the general object is incomplete
Do not make a class abstract merely because inheritance exists. The design should need a meaningful shared role whose required behaviour cannot sensibly be completed at the parent level.
Abstraction is not encapsulation
| Question | Abstraction | Encapsulation |
|---|---|---|
| Design focus | What essential operations should other code be able to rely on? | How should internal state and implementation be protected or controlled? |
| Animal example | Every concrete Animal must provide activity(). | name is kept behind controlled methods rather than exposed for arbitrary mutation. |
| Main benefit | Stable common view and lower coupling between modules. | Integrity of internal state and a controlled public interface. |
interface lesson.Check the abstraction
Explain the design reason, not just the keyword.
-
T23 allowed new Animal("Nori") because Animal supplied a default activity(). After Animal becomes abstract and activity() becomes abstract, should that line still be allowed?
Reveal model answer
No. The design now says that a general Animal is deliberately incomplete. Only a concrete subclass that supplies the required activity() behaviour should be instantiated.
-
Does an abstract class have to contain only abstract methods?
Reveal model answer
No. It may contain shared state, a constructor and fully implemented methods. In this model, name, the constructor and label() are shared; only activity() is abstract.
-
A concrete Bird subclass inherits abstract activity() but does not implement it. What is the important consequence?
Reveal model answer
Bird is still incomplete. Java rejects a concrete Bird class that fails to implement the method; Python ABC prevents an incomplete Bird from being instantiated. The caller can therefore rely on every concrete Animal providing activity().
-
How is abstraction different from encapsulation?
Reveal model answer
Abstraction decides the essential common view and required operations that other code should depend on. Encapsulation controls access to internal state and implementation details. They often work together, but they solve different design problems.
How much code should you be able to write?
B3.2.3 uses the command term Explain, so this is not another large construction standard. You should still be able to read and complete a small abstract-class model, identify an invalid instantiation, repair a concrete subclass that has not fulfilled the contract, and explain why the design improves modularity.
Challenges Choose one
Choose a challenge that feels appropriate for you. Code heat is only a rough estimate, not a fixed level.
Complete the Abstract Animal
SelectedComplete the supplied abstract Animal hierarchy. Animal must keep shared name state and an implemented label() method, but activity() must be abstract. Complete Dog and Human so that they satisfy the required operation, then process both objects through one Animal[] loop. Keep an invalid attempt to instantiate Animal commented out and add a short explanation of why the design deliberately prevents that object from existing.
Repair the Missing Contract
SelectedThe supplied Bird class extends abstract Animal but does not implement activity(). Predict the compiler problem, repair Bird, run the corrected program and add concise comments explaining why the abstract method acts as a useful contract for code that works with Animal objects. Also state one difference between abstraction and encapsulation.
Selected challenge
This choice is shared with the portfolio setup page.
Plan your solution in handwritten pseudocode
Before opening your IDE or writing any program code, handwrite pseudocode for this challenge on paper.
Not marked complete. If you submit now, the GitHub README will record “No”.
Create your challenge folder
Run this command after planning. It creates the correct empty folder inside your portfolio.
Complete the challenge
Use your handwritten pseudocode as the starting plan, then write and test your solution in the folder created above.
Optional two-level scaffold
Try from your handwritten pseudocode first. Scaffold gives some structure; Scaffold + comments gives stronger guidance. Use only the level you need, and update your pseudocode first if the support changes your plan.
Submit for review
Run this when your program is complete. It creates the README, commits the folder and pushes it. The README records whether you marked the handwritten pseudocode as complete; the paper itself is handed to your teacher separately.