Java Inheritance Mini Project (Teacher Version)
Includes: typed project spec, teaching notes, full solution, and TicketDemo example run.
Mini Project Instructions (Typed)
STEP 1: The Base Class — Ticket
Define a class (that cannot be constructed) named Ticket.
Instance variables:
- int serialNumber
- static int nextSerialNumber = 1000
Note: Every ticket will have a serial number that will be automatically generated.
Assign the static field to serialNumber and then increment nextSerialNumber.
Constructor:
- No parameters
- Assign serialNumber = nextSerialNumber++
Methods:
- public int getSerialNumber()
- public abstract double getPrice()
- public String toString()
STEP 2: Core Subclasses
1) WalkUpTicket
- Price: $50
- Implements getPrice() to return 50.
2) AdvanceTicket
- Instance variable: daysInAdvance
- Price rules:
- 10 days or more: $30
- Fewer than 10 days: $40
3) StudentAdvanceTicket
- Extends AdvanceTicket
- Price = half of regular advance ticket price. Use [Link]() to get the base value.
- toString() should also include "(ID required)"
STEP 3: Additional Subclasses
4) GroupTicket
- Instance variable: groupSize
- Price rules:
- Fewer than 10 people: $45 per ticket
- 10 people or more: $40 per ticket
- Add method: public double getTotalCost()
- returns price * groupSize
- toString() should include "Group size: x, Total: $..."
5) SeasonPass
- Instance variables: String holderName, int durationMonths
- Pricing:
- 6 months = $300
- 12 months = $500
- toString() should include holder name and duration (e.g., "Holder: Lena, Duration: 12
months")
6) ChildTicket
- Instance variable: int age
- Price rules:
- Under age 5: Free
- Age 5–11: Half of WalkUpTicket price ($25)
- toString() should include child's age
7) (Optional Challenge) ComboTicket
- Includes both park entry and food credit
- Instance variable: double foodCredit
- Price = WalkUpTicket price + foodCredit
- Customize toString() to include food credit description
STEP 4: Demo Class — TicketDemo
Write a class with a main() method to test your hierarchy:
1) Create an ArrayList<Ticket> (or an array of Ticket references)
2) Add one of each type of ticket into the list
3) Loop through and print each ticket using [Link]()
Teaching Notes (What This Targets)
Abstract class: Ticket cannot be instantiated; enforces getPrice() in subclasses.
Static field: nextSerialNumber is shared across ALL Ticket objects (one counter for the
whole hierarchy).
Constructor chaining: Ticket() runs before any subclass constructor body, ensuring
serialNumber is always assigned.
Overriding: Each subclass computes price differently; dynamic dispatch chooses the
correct getPrice() at runtime.
Extending behavior: [Link]() should use [Link]() then
append '(ID required)'.
Polymorphism: ArrayList<Ticket> can hold different ticket types; printing calls each
object’s overridden toString().
Full Reference Solution (with comments)
public abstract class Ticket {
protected int serialNumber;
protected static int nextSerialNumber = 1000;
// Base constructor runs FIRST for every ticket object (before
subclass constructor body)
public Ticket() {
serialNumber = nextSerialNumber++;
public int getSerialNumber() {
return serialNumber;
// Forces every subclass to define its own pricing rule
public abstract double getPrice();
@Override
public String toString() {
return "Number: " + serialNumber + ", Price: $" + getPrice();
public class WalkUpTicket extends Ticket {
@Override
public double getPrice() {
return 50;
public class AdvanceTicket extends Ticket {
protected int daysInAdvance;
public AdvanceTicket(int daysInAdvance) {
[Link] = daysInAdvance;
@Override
public double getPrice() {
return (daysInAdvance >= 10) ? 30 : 40;
public class StudentAdvanceTicket extends AdvanceTicket {
public StudentAdvanceTicket(int daysInAdvance) {
super(daysInAdvance);
@Override
public double getPrice() {
return [Link]() / 2;
}
@Override
public String toString() {
// Keep normal ticket information + add the student requirement
return [Link]() + " (ID required)";
public class GroupTicket extends Ticket {
private int groupSize;
public GroupTicket(int groupSize) {
[Link] = groupSize;
@Override
public double getPrice() {
return (groupSize >= 10) ? 40 : 45;
public double getTotalCost() {
return getPrice() * groupSize;
@Override
public String toString() {
return [Link]() + ", Group size: " + groupSize + ",
Total: $" + getTotalCost();
}
public class SeasonPass extends Ticket {
private String holderName;
private int durationMonths;
public SeasonPass(String holderName, int durationMonths) {
[Link] = holderName;
[Link] = durationMonths;
@Override
public double getPrice() {
return (durationMonths == 6) ? 300 : 500; // assumes only 6 or
12 per spec
@Override
public String toString() {
return [Link]() + ", Holder: " + holderName + ",
Duration: " + durationMonths + " months";
public class ChildTicket extends Ticket {
private int age;
public ChildTicket(int age) {
[Link] = age;
@Override
public double getPrice() {
if (age < 5) return 0;
if (age <= 11) return 25;
// Not specified for >11; treat as regular walk-up
return 50;
@Override
public String toString() {
return [Link]() + ", Child age: " + age;
/* Optional Challenge */
public class ComboTicket extends Ticket {
private double foodCredit;
public ComboTicket(double foodCredit) {
[Link] = foodCredit;
@Override
public double getPrice() {
return 50 + foodCredit; // WalkUpTicket price + food credit
}
@Override
public String toString() {
return [Link]() + " (includes $" + foodCredit + " food
credit)";
import [Link];
public class TicketDemo {
public static void main(String[] args) {
ArrayList<Ticket> tickets = new ArrayList<>();
[Link](new WalkUpTicket()); // 50
[Link](new AdvanceTicket(12)); // 30
[Link](new StudentAdvanceTicket(12)); // 15 + ID
required
[Link](new GroupTicket(10)); // 40 each; total
400
[Link](new SeasonPass("Maria Lopez", 12)); // 500
[Link](new ChildTicket(10)); // 25
[Link](new ComboTicket(10)); // 60 includes $10
food credit
for (Ticket t : tickets) {
[Link](t);
}
}
Expected Output (Example)
Number: 1000, Price: $50.0
Number: 1001, Price: $30.0
Number: 1002, Price: $15.0 (ID required)
Number: 1003, Price: $40.0, Group size: 10, Total: $400.0
Number: 1004, Price: $500.0, Holder: Maria Lopez, Duration: 12 months
Number: 1005, Price: $25.0, Child age: 10
Number: 1006, Price: $60.0 (includes $10.0 food credit)