Inheritance and polymorphism are the cornerstones of object-oriented programming that allow you to write less code while making it more flexible and easier to maintain. They solve the fundamental problem of code duplication and rigidity, which matters immensely for the 1Z0-829 exam because this objective tests your ability to design and implement hierarchical class structures and understand method dispatch at runtime.
Jump to a section
A simple way to picture Inheritance and Polymorphism
Because your grandmother created a master recipe book, every family member can cook from it without having to reinvent the wheel. This leads to a kitchen where each person can take the same base recipe and make it their own.
Think about your grandmother's original recipe for a simple tomato sauce. It lists the core ingredients: tomatoes, garlic, olive oil, and basil. That original recipe is like a 'superclass' in Java — a general, foundational template. Now, your aunt wants to make a spicy version. She doesn't rewrite the entire recipe book. Instead, she creates a new page that says 'Spicy Tomato Sauce: Same as Grandmother's recipe, but add two chillies and a pinch of cayenne.' This new page is a 'subclass'. It 'inherits' all the ingredients and steps from the original superclass recipe. She only needs to write down what's different.
Your cousin, on the other hand, follows the exact same original recipe but adds a splash of cream at the end to make a creamy version. The underlying act of following the recipe stays the same — you still boil, crush, and simmer. But the final dish changes based on which specific version you choose. This is 'polymorphism'. In programming, polymorphism lets you use a single instruction — 'makeSauce()' — and have it execute differently depending on whether it's the spicy version, the creamy version, or the original. The kitchen doesn't care which family member is cooking; it just knows to follow the recipe. The result is flexibility and reusability, which is exactly what inheritance and polymorphism give to code.
Inheritance is a mechanism in Java that allows one class to acquire the properties (fields) and behaviours (methods) of another class. The class that is inherited from is called the 'superclass' or 'parent class'. The class that receives the inheritance is called the 'subclass' or 'child class'. Think of it like a family tree: a child inherits traits from a parent, but can also have its own unique traits.
To create a subclass, you use the 'extends' keyword. For example, if you have a class called 'Animal' (the superclass) with a method 'eat()', you can create a subclass called 'Dog' that extends 'Animal'. The 'Dog' class automatically has the 'eat()' method without you having to rewrite it. You can then add new methods to 'Dog', like 'bark()', or you can change how 'eat()' works specifically for dogs. Changing how a method works in a subclass is called 'method overriding'.
Method overriding is crucial. It means you write a new version of a method in the subclass that has the exact same name, return type, and parameters as the method in the superclass. When you call that method on a Dog object, Java will run the Dog's version, not the Animal's version. This is the heart of polymorphism: the ability of an object to take many forms.
Polymorphism literally means 'many forms'. In Java, it works through inheritance. You can write code that refers to a variable as the superclass type but actually holds an object of a subclass. For instance, you can declare a variable of type 'Animal' but assign it a new 'Dog' object. When you call the 'eat()' method on that variable, Java will look at the actual object type (Dog) and run the Dog's overridden version of 'eat()'. This decision happens at runtime — not when you compile the code — and is called 'dynamic method dispatch' or 'virtual method invocation'.
Why does this exist? Before inheritance, if you wanted a 'Dog' that could eat and a 'Cat' that could eat, you would write two completely separate classes, each with its own 'eat()' method. If you wanted to change how eating works, you'd have to change it in both classes. Inheritance centralises shared code in the superclass. Polymorphism then allows you to write a single method that can handle any type of animal, like 'public void feedAnimal(Animal a) { a.eat(); }'. You can pass any Animal subclass (Dog, Cat, Bird) to this method, and it will automatically call the correct 'eat()' version. This replaces the need for long 'if-else' chains checking the type of animal.
The 'Object' class is the ultimate superclass in Java. Every class in Java, directly or indirectly, extends the 'Object' class. This means all objects inherit a set of fundamental methods, including 'toString()', 'equals()', and 'hashCode()'. You can override these methods in your own classes to give them custom behaviour. For example, overriding 'toString()' allows you to control what text is printed when you print your object.
Finally, there are 'abstract classes'. An abstract class is a class that cannot be instantiated — you cannot create an object directly from it. It is designed to be a superclass only. You declare an abstract class with the 'abstract' keyword. It can contain both regular methods (with a body) and 'abstract methods' (declared without a body, ending with a semicolon). An abstract method is a contract: any concrete (non-abstract) subclass must provide an implementation for that method. For example, you might have an abstract class 'Shape' with an abstract method 'calculateArea()'. Subclasses like 'Circle' and 'Rectangle' must each provide their own version of 'calculateArea()'. This forces a common interface across different shapes while letting each define its own logic.
The key syntax to remember: - 'extends' for class-to-class inheritance. - 'implements' for class-to-interface inheritance (interfaces are another type of contract, covered in a different chapter). - '@Override' annotation above a method to indicate you are overriding a superclass method (optional but best practice — it catches errors). - 'super' keyword to call the superclass constructor or methods from the subclass. - 'final' keyword on a class prevents it from being subclassed; 'final' on a method prevents it from being overridden.
Identify the Commonality
Look at your classes and find fields and methods that are repeated. For example, 'name' and 'age' appear in both 'Employee' and 'Customer'. This tells you where to put the superclass.
Create the Superclass
Write a class that contains the common fields and methods. Make it 'abstract' if it should never be instantiated on its own. Use 'private' for fields, and provide public getters/setters.
Use 'extends' to Create Subclasses
For each subclass, write 'public class SubClassName extends SuperClassName'. The subclass now has access to all non-private members of the superclass.
Override Methods as Needed
In the subclass, write a method with the exact same signature as one in the superclass. Use the '@Override' annotation to let the compiler check your work. The subclass method will execute when called on a subclass object.
Handle Constructors with 'super()'
In the subclass constructor, the first line must call a superclass constructor. If the superclass has a no-arg constructor, Java adds 'super()' automatically. Otherwise, you must write 'super(parameters)' manually.
Use Polymorphism in Variables and Methods
Declare variables with the superclass type but assign subclass objects. Write methods that take the superclass as a parameter. This allows you to pass any subclass to that method.
Test with 'instanceof' for Safe Casting
When you need to use a subclass-specific method, check the object's type with 'if (obj instanceof SubClass)' before casting. This prevents ClassCastException at runtime.
An IT professional, say a backend developer at an e-commerce company, uses inheritance and polymorphism every day to manage product types. Imagine the company sells physical items (books, electronics) and digital items (e-books, software licences). Without inheritance, the developer would have to write a separate class for each product type, each with its own 'calculateShippingCost()' or 'applyDiscount()' method. If a business rule for discounts changes, they would need to edit every single class.
Instead, the developer builds a superclass called 'Product' with common fields like 'price', 'name', and 'id'. It also has a method 'getDiscountedPrice()' with a default discount logic. Then they create subclasses: 'PhysicalProduct' and 'DigitalProduct'. Each subclass overrides 'getDiscountedPrice()' because the logic differs. Physical products might have a shipping surcharge in the discount, while digital products might have a flat percentage off with no shipping.
Step by step, this is what happens in a real project:
The developer defines the 'Product' superclass with fields and a basic method.
They create 'PhysicalProduct extends Product' and override 'getDiscountedPrice()' to include shipping costs.
They create 'DigitalProduct extends Product' and override 'getDiscountedPrice()' to apply a simple percentage discount.
They define a method 'processOrder(Product p)' that takes any Product type and calls p.getDiscountedPrice(). The right discount is applied automatically.
Later, the business adds 'SubscriptionProduct'. The developer simply creates a new subclass, overrides the method, and passes it to 'processOrder()' — the existing method works without changes.
This scenario maps directly to the exam. The developer will use: - 'abstract class' if they want to force every product to have a discount calculation but don't want a default. - 'method overriding' to change the discount calculation per product type. - 'polymorphism' in the 'processOrder' method, where the parameter type is the superclass. - 'Object class' methods like 'toString()' overridden to print product details nicely.
The exam will test whether you know which method runs when. For instance, if 'DigitalProduct' does not override 'getDiscountedPrice()', then calling it on a DigitalProduct object will use the default from 'Product'. If it does override, the overridden version runs. This is the core of the 'virtual method invocation' trap.
Additionally, the developer must ensure constructors chain correctly. Every subclass constructor must call the superclass constructor, either implicitly (if the superclass has a no-argument constructor) or explicitly using 'super()'. If the superclass only has a parameterised constructor, the subclass must call 'super(parameters)' as the first line of its constructor. This is a frequent exam pitfall.
The 1Z0-829 exam tests inheritance and polymorphism relentlessly. Expect at least 5-6 questions across the exam that touch on these concepts, either directly or indirectly. The questions are designed to catch you out on subtle rules.
The most tested topics:
Method overriding rules: the overriding method must have the same name, same parameters, and a compatible return type (covariant return types are allowed, meaning a subclass can return a more specific type). It cannot have a more restrictive access modifier (e.g., you cannot override a 'public' method with a 'protected' one). It cannot throw a broader checked exception than the original.
'super' keyword usage: 'super.method()' calls the superclass version; 'super()' calls the superclass constructor. The compiler forces 'super()' to be the first statement in a constructor.
Abstract classes and methods: a class with an abstract method must be declared abstract. A concrete subclass must implement all abstract methods, or it must also be declared abstract.
Object class methods: 'toString()', 'equals()', 'hashCode()'. Know the default behaviour and how to override them correctly. The contract between 'equals()' and 'hashCode()' is critical: if two objects are equal by 'equals()', they must have the same hash code. Violating this breaks hash-based collections like HashSet and HashMap.
Final keyword: a final class cannot be extended. A final method cannot be overridden. This is often tested in combination with inheritance.
Constructor chaining: every constructor in a subclass calls a constructor of the superclass. If the superclass has no no-arg constructor, the subclass must explicitly call 'super(args)'. If not provided, the compiler inserts 'super()' automatically, which will fail if the superclass does not have one.
Traps they set:
They give you a superclass with a private method and a subclass with a method of the same name and signature. Private methods are not inherited, so this is not overriding — it's a completely new method. The exam will ask what prints when you call the method on a subclass reference vs a superclass reference.
They give you an abstract class with a constructor that takes parameters, and a subclass that forgets to call 'super()' explicitly. The code will not compile.
They mix up overloading and overriding. Overloading is having the same method name but different parameters in the same class. Overriding is redefining a method in a subclass with the same signature. They often put both in a question to confuse you.
They test 'instanceof' operator: 'if (obj instanceof SubClass)' returns true if obj is an instance of SubClass or any of its subclasses. They will ask you to determine if a cast is safe.
Correct answer pattern: Always check whether the method being called is inherited, overridden, or hidden (for static methods). Static methods are not polymorphic — they are resolved at compile-time based on the reference type, not the object type. For instance methods, the actual object type at runtime decides which version runs. Look for the '@Override' annotation as a clue that the student intended overriding, but the annotion is optional, so you must verify the signature matches.
Key definitions to memorise: - 'Virtual method invocation': the process by which the JVM decides at runtime which overridden method to call based on the actual object type. - 'Covariant return type': the overriding method can return a subtype of the original return type. - 'Abstract method': a method declaration without a body, ending with a semicolon, that must be implemented by a concrete subclass. - 'Concrete class': a class that is not abstract and can be instantiated.
Inheritance uses the 'extends' keyword to create a subclass that reuses fields and methods from a superclass.
Method overriding requires the exact same method signature (name, parameters, return type) and the same or more accessible access modifier.
Polymorphism allows a superclass reference variable to hold a subclass object, and the correct overridden method runs at runtime.
The 'Object' class is the root of all class hierarchies; every class inherits its methods like 'toString()', 'equals()', and 'hashCode()'.
An abstract method has no body and forces every concrete subclass to provide its own implementation.
A 'final' class cannot be extended; a 'final' method cannot be overridden.
Static methods are not polymorphic - they are resolved at compile-time based on the reference type, not the object type.
Every subclass constructor must call a superclass constructor, either implicitly (default no-arg) or explicitly with 'super()'.
These come up on the exam all the time. Here's how to tell them apart.
Method Overriding
Applies to instance methods only.
Resolved at runtime based on object type.
The subclass method must have the same signature and be at least as accessible.
Method Hiding (Static Methods)
Applies to static methods only.
Resolved at compile-time based on reference type.
The subclass static method can have a different signature; it 'hides' the parent's static method, not override it.
Abstract Class
Cannot be instantiated directly.
May contain abstract methods (no body).
Designed to be a base for subclasses.
Concrete Class
Can be instantiated directly using 'new'.
Cannot contain abstract methods (unless declared abstract itself).
Can stand alone as an independent class.
'super' Keyword (Constructor)
Calls a constructor of the immediate superclass.
Must be the first statement in a constructor.
Used to pass arguments to the parent constructor.
'this' Keyword (Constructor)
Calls another constructor in the same class.
Must be the first statement when used in a constructor.
Used to avoid code duplication within the same class.
Inherited Method
The subclass does not define the method at all.
The method from the superclass is used as-is.
Calling the method runs the superclass version.
Overridden Method
The subclass defines a method with the same signature as the parent.
The subclass version replaces the parent version for subclass objects.
Calling the method runs the subclass version due to polymorphism.
Mistake
A subclass inherits private members of the superclass.
Correct
A subclass does not inherit private members. Private fields and methods are only accessible within the class that defines them. They are not visible to subclasses.
Because private is the most restrictive access modifier. Beginners often think inheritance means copying all code, but it only applies to accessible members.
Mistake
If a superclass method is marked 'final', you can still hide it by creating a static method with the same name in the subclass.
Correct
No, a final method cannot be overridden or hidden. The compiler will give an error. Final is a hard lock.
People confuse static method hiding with overriding. Both are prevented by 'final'. The rule is absolute.
Mistake
An abstract class cannot have a constructor.
Correct
An abstract class can have constructors. They are called when a concrete subclass is instantiated, usually to initialise fields declared in the abstract class.
Because you cannot use 'new' on an abstract class directly, beginners assume constructors are useless. But constructors are still executed as part of subclass instantiation.
Mistake
Using 'super.method()' in a subclass calls the method of the superclass's parent, not the immediate superclass.
Correct
The 'super' keyword always refers to the immediate parent class. It does not skip generations. To call a grandparent's method, you would need a different approach like creating a method in the parent that calls the grandparent's method.
The name 'super' sounds like it might refer to the highest ancestor, but it literally refers to the direct superclass. This is a source of many off-by-generation errors.
Mistake
If class B extends class A, and class C extends class B, then class C can use 'super' to call a constructor in class A directly.
Correct
Class C can only call its immediate superclass constructor, class B's constructor. Class B may then chain to class A. Direct calls to grandparent constructors are not allowed.
Constructor chaining is sequential. Each level only knows its parent. This prevents breaking encapsulation in the chain.
Reveal each answer, then mark whether you got it right. Score 60%+ to unlock the next chapter.
Overloading is defining multiple methods with the same name but different parameters in the same class. Overriding is redefining a method with the same signature in a subclass. Overloading is compile-time, overriding is runtime.
No, constructors are not inherited. A subclass must define its own constructors. However, a subclass constructor must call a superclass constructor using 'super()' as its first statement.
Nothing bad, the method still overrides if the signature matches. '@Override' is an optional annotation that helps the compiler catch mistakes if you accidentally misspell the method name or change the parameters.
No, you cannot use 'new' directly on an abstract class. You can only create objects from concrete subclasses that implement all abstract methods.
To avoid the 'diamond problem' where a class could inherit conflicting methods from two parents. Java uses interfaces instead, which do allow a form of multiple inheritance through 'implements'.
The actual object type determines which method runs. If the variable holds a subclass object and the subclass overrides the method, the subclass version runs. This is called virtual method invocation.
You've finished Inheritance and Polymorphism. Continue through the 1Z0-829 study guide to build a complete picture of the exam.
Done with this chapter?