Inheritance, Polymorphism, and OOP Design, CS312 – Study Notes
offline

Difficulty: Intermediate | Prerequisites: Expression evaluation, basic Java syntax, classes and objects fundamentals

Big Picture

Object-oriented programming is the backbone of Java. In CS312, you move from writing isolated methods to building class hierarchies where subclasses inherit and specialise behaviour. This is where the course shifts from "write code that works" to "design code that is organised."

Inheritance and polymorphism let you write flexible code that handles families of related objects without duplicating logic. If you have not yet worked through basic class syntax (fields, constructors, methods), review that material before reading these notes. The Critter assignment brings all of these ideas together in a concrete, testable way.


TL;DR

Subclasses extend superclasses to inherit fields and methods, and can override methods to provide specialised behaviour. Assignments must respect the class hierarchy: a subclass object can go into a superclass variable (polymorphism), but not the other way around without an explicit cast. The Critter-style assignments test all of this by asking you to implement subclasses with overridden movement, fighting, and eating methods.


Key Terms

Inheritance

A mechanism where one class (the subclass) acquires the fields and methods of another class (the superclass) using the extends keyword. Think of it as: the child class gets everything the parent has, and can add or change things on top.

Subclass / child class

The class that extends another. It inherits all non-private members of the superclass and may override methods or add new ones.

Superclass / parent class

The class being extended. It defines the shared behaviour and fields that subclasses inherit.

Polymorphism

The ability to treat a subclass object as if it were a superclass object. A variable of type Computer can hold a PC object. In simple terms, the variable's declared type determines what methods you can call, but the object's actual type determines which version runs.

Method overriding

When a subclass provides its own implementation of a method that already exists in the superclass. The method must have the same name, return type, and parameter list. Think of it as: the subclass says "I'll handle this my own way."

super()

A call to the superclass constructor from within a subclass constructor. Must be the first statement in the subclass constructor. super() calls the no-argument constructor; super(value) calls the constructor that takes that parameter type.

Enum

A fixed set of named constants, such as Direction.NORTH or Attack.ROAR. Enums prevent invalid values and make code more readable. In the Critter assignments, Direction and Attack are enums used for movement and fighting.

Instance variable

A field declared in a class that each object gets its own copy of. Used in Critter subclasses to track state such as steps taken, current direction, or movement phase.


Inheritance, Class Hierarchies, and Legal Assignments

The extends keyword

  • class PC extends Computer means PC is a subclass of Computer. PC inherits all of Computer's public and protected fields and methods.

  • A subclass can add new fields and methods, or override inherited methods.

Constructor chaining with super()

  • Every subclass constructor must call a superclass constructor. If you do not write a super() call, Java inserts super() (no arguments) automatically.

  • If the superclass does not have a no-argument constructor, you must call super(parameters) explicitly, or you get a compile error.

  • The super() call must be the very first statement in the subclass constructor.

Legal and illegal assignments

The rule is straightforward: a variable of a superclass type can hold a subclass object, but not the other way around.

  • PC p1 = new PC(16); is legal, provided PC has a constructor that takes an int.

  • Computer c1 = new PC(); is legal (polymorphism). The variable type is Computer, but the object is a PC. If Computer has a default constructor, this compiles.

  • Mac m1 = new Computer(12); causes a compile error. Computer is not a subclass of Mac. You cannot store a superclass object in a subclass variable without an explicit cast, and even then, a ClassCastException occurs at runtime if the object is not actually a Mac.

Type compatibility summary

  • Subclass object into superclass variable: always legal (widening).

  • Superclass object into subclass variable: compile error without a cast, runtime error if the cast is wrong.

  • Unrelated classes: always a compile error.

Method Overriding and Critter Class Design

Overriding methods

  • To override a method, the subclass method must have the exact same name, return type, and parameter list as the superclass method.

  • The @Override annotation is optional but strongly recommended. It tells the compiler to check that you are overriding correctly.

  • When a method is called on a polymorphic reference, Java uses the actual object's type (not the variable's declared type) to decide which version runs. This is called dynamic dispatch.

Critter class pattern

The Critter assignments (Yak, JumpingBean, etc.) follow a consistent pattern:

  • Instance variables: track internal state such as steps taken, maximum steps per leg, current direction, and whether the critter is moving or stationary.

  • fight(): returns an Attack enum value. The choice often depends on the critter's current state. For example, JumpingBean returns SCRATCH when not moving and FORFEIT when moving.

  • getMove(): returns a Direction enum value. Typically involves incrementing a step counter, checking whether the current leg of movement is finished, toggling between moving and stationary states, and selecting a new direction.

  • eat(): returns a boolean indicating whether the critter eats.

Using enums

  • Direction values: NORTH, SOUTH, EAST, WEST, CENTER.

  • Attack values: ROAR, POUNCE, SCRATCH, FORFEIT.

  • Use Math.random() to select directions with equal probability. For example, to choose between four directions with equal chance: generate a random number between 0 and 1, and map ranges of 0.25 each to a direction.

Real-world application

The Critter pattern is a simplified version of how game engines work. Each entity in a game has its own state and behaviour methods that get called each frame. The inheritance structure lets you define shared logic in a base class while each creature type specialises its own movement and combat patterns.


Common Misconceptions

  • Students often think a superclass reference can call subclass-only methods. It cannot. If the variable is declared as Computer, you can only call methods that exist in Computer, even if the actual object is a PC with extra methods.

  • Students often think overriding and overloading are the same thing. They are not. Overriding replaces a superclass method with the same signature. Overloading creates a new method with a different parameter list.

  • Students often think super() is optional when the superclass has no default constructor. It is not. If the superclass only has parameterised constructors, you must call super(args) explicitly or the code will not compile.

  • Students often forget that Math.random() returns a double from 0.0 (inclusive) to 1.0 (exclusive), not an int. To get an int in a range, multiply and cast: (int)(Math.random() * n) gives 0 through n-1.


Why It Matters / Exam Flags

⚠️ Legal assignment questions are a staple. You will see several Type var = new Type(args); lines and must say which compile and which do not.

⚠️ The Critter-style implementation question requires you to write a complete subclass with instance variables, a constructor, and overridden methods. Practice writing these from scratch, not just reading them.

⚠️ Polymorphism tracing: when a method is called on a superclass reference that holds a subclass object, the subclass version runs. Exams test this with class hierarchies and ask what gets printed.

⚠️ Constructor chaining errors are common. If you see a compile error question involving super(), check whether the superclass has a matching constructor.


Quick Self-Test

  1. True or false: Computer c = new PC(); is legal if PC extends Computer. (True.)

  1. True or false: PC p = new Computer(); is legal. (False. A superclass object cannot be assigned to a subclass variable without a cast.)

  1. Fill in the blank: when a subclass constructor does not explicitly call super(), Java inserts a call to ____. (The no-argument superclass constructor.)

  1. True or false: method overriding requires the same method name but can have a different return type. (False. Same name, same return type, same parameters.)

  1. Fill in the blank: Math.random() returns a value from ____ (inclusive) to ____ (exclusive). (0.0, 1.0)


Practice Q&A

Q: Given the hierarchy Computer > PC and Computer > Mac, is Mac m1 = new Computer(12); legal? Why or why not?

A: No. Computer is a superclass of Mac, not a subclass. You cannot assign a superclass object to a subclass reference. This causes a compile error.

Q: If Computer has a method getMemory() and PC overrides it, what happens when you call c.getMemory() where Computer c = new PC(16);?

A: PC's version of getMemory() runs. The declared type is Computer, but the actual object is a PC. Java uses dynamic dispatch to call the overridden method.

Q: A JumpingBean critter returns SCRATCH when not moving and FORFEIT when moving. Write the fight() method.

A: public Attack fight(String opponent) { if (moving) { return Attack.FORFEIT; } else { return Attack.SCRATCH; } } where moving is a boolean instance variable tracking whether the critter is currently in motion.

Q: What happens if a subclass constructor does not call super() and the superclass only has public Computer(int memory) as its constructor?

A: Compile error. Java tries to insert super() (no arguments), but no such constructor exists in the superclass. You must write super(someIntValue) explicitly.


Connections to Other Topics

Inheritance and polymorphism build on the basic class and object concepts from earlier in CS312. They also connect directly to code tracing: exam questions often combine polymorphic method calls with expression evaluation (covered in the Expression Evaluation study notes).

The Critter assignments tie OOP design to arrays and data processing. A critter's getMove() method often involves step counters and modular arithmetic, while fight() may use conditional logic that mirrors the pattern-matching covered in the Arrays and Data Processing study notes.


Related Terms / Search Tags

Java inheritance CS312, extends keyword, polymorphism Java, method overriding vs overloading, super constructor call, subclass superclass assignment, type compatibility Java, dynamic dispatch, Critter class CS312, JumpingBean Yak implementation, enum Direction Attack, Math.random Java, instance variables OOP, legal illegal object assignment, UT Austin CS312 OOP