Introduction
In this lab, we'll explore two fundamental concepts of object-oriented programming in Java: inheritance and polymorphism. These powerful features allow us to create more organized, efficient, and flexible code. We'll start by exploring inheritance, which enables us to create new classes based on existing ones, and then move on to polymorphism, which allows us to treat objects of different classes in a uniform way.
By the end of this lab, you'll be able to:
- Create class hierarchies using inheritance
- Override methods in subclasses
- Understand and use polymorphism
- Implement abstract classes and methods
Don't worry if these terms sound complex – we'll break everything down into simple, easy-to-follow steps. Let's begin our exciting journey to enhance your Java programming skills!
Creating a Base Class
We'll start by creating a base class called Animal. This class will serve as the foundation for our other classes.
Open your terminal and navigate to your project directory:
cd ~/projectCreate a new file called
Animal.javausing the touch command:touch Animal.javaOpen
Animal.javain your text editor and add the following code:public class Animal { private String name; private int age; public Animal(String name, int age) { this.name = name; this.age = age; } public void eat() { System.out.println(name + " is eating."); } public void sleep() { System.out.println(name + " is sleeping."); } public String getName() { return name; } public int getAge() { return age; } }Let's break down this code:
- We define a class named
Animalwith two attributes:name(a String) andage(an int). - The
privatekeyword means these attributes can only be accessed within the class. - We have a constructor that initializes these attributes when an
Animalobject is created. - We have two methods:
eat()andsleep(), which print what the animal is doing. - We also have "getter" methods (
getName()andgetAge()) that allow us to access the private attributes from outside the class.
- We define a class named
Save the
Animal.javafile.
Now, let's compile our
Animalclass to make sure there are no errors. In your terminal, run:javac Animal.javaIf there are no error messages, your class compiled successfully!
Creating a Subclass
Now that we have our base Animal class, let's create a subclass called Dog. This will demonstrate how inheritance works in Java.
In your terminal, create a new file called
Dog.java:touch Dog.javaOpen
Dog.javain your text editor and add the following code:public class Dog extends Animal { private String breed; public Dog(String name, int age, String breed) { super(name, age); // Call the superclass constructor this.breed = breed; } public String getBreed() { return breed; } }Let's break down this new code:
extends Animaltells Java thatDogis a subclass ofAnimal. WhileDoginherits fromAnimal, the private attributesnameandageinAnimalare not directly accessible inDog. However,Dogcan access these attributes through the inherited public getter methodsgetName()andgetAge().- We've added a new attribute
breedthat's specific toDog. - The constructor takes three parameters. It uses
super(name, age)to call theAnimalconstructor, then sets thebreed. - We've added a new method
getBreed()that's specific toDog.
Save the
Dog.javafile.Compile the
Dogclass:javac Dog.javaYou might see a warning about Animal.class, but that's okay for now.
Demonstrating Inheritance
Now that we have our Animal and Dog classes, let's create a program to demonstrate how inheritance works.
Create a new file called
InheritanceDemo.java:touch InheritanceDemo.javaOpen
InheritanceDemo.javaand add the following code:public class InheritanceDemo { public static void main(String[] args) { Animal genericAnimal = new Animal("Generic Animal", 5); Dog myDog = new Dog("Buddy", 3, "Labrador"); System.out.println("Demonstrating Animal class:"); genericAnimal.eat(); genericAnimal.sleep(); System.out.println("\nDemonstrating Dog class:"); myDog.eat(); // Inherited from Animal myDog.sleep(); // Inherited from Animal System.out.println("\nDog details:"); System.out.println("Name: " + myDog.getName()); // Inherited method System.out.println("Age: " + myDog.getAge()); // Inherited method System.out.println("Breed: " + myDog.getBreed()); // Dog-specific method } }This program creates instances of both
AnimalandDogclasses and demonstrates how theDogclass inherits methods from theAnimalclass.Save the
InheritanceDemo.javafile.Compile and run the program:
javac InheritanceDemo.java java InheritanceDemoYou should see output similar to this:
Demonstrating Animal class: Generic Animal is eating. Generic Animal is sleeping. Demonstrating Dog class: Buddy is eating. Buddy is sleeping. Dog details: Name: Buddy Age: 3 Breed: Labrador
This demonstration shows how the Dog class inherits attributes and methods from the Animal class, while also adding its own specific attribute (breed) and method (getBreed()).
Method Overriding
Method overriding is a feature that allows a subclass to provide a specific implementation of a method that is already defined in its superclass. Let's see how this works.
Open
Dog.javaand add the following method:@Override public void eat() { System.out.println(getName() + " is eating dog food."); }Add this method inside the
Dogclass, but outside of any other methods.The
@Overrideannotation tells the compiler that we intend to override a method from the superclass. It's not required, but it's good practice to use it.Save the
Dog.javafile.Now, let's modify our
InheritanceDemo.javato demonstrate method overriding. OpenInheritanceDemo.javaand replace its content with:public class InheritanceDemo { public static void main(String[] args) { Animal genericAnimal = new Animal("Generic Animal", 5); Dog myDog = new Dog("Buddy", 3, "Labrador"); System.out.println("Demonstrating method overriding:"); genericAnimal.eat(); myDog.eat(); System.out.println("\nDemonstrating inherited method:"); myDog.sleep(); // This method is still inherited from Animal System.out.println("\nDog details:"); System.out.println("Name: " + myDog.getName()); System.out.println("Age: " + myDog.getAge()); System.out.println("Breed: " + myDog.getBreed()); } }Save the
InheritanceDemo.javafile.Compile and run the updated program:
javac Animal.java Dog.java InheritanceDemo.java java InheritanceDemo
You should see output similar to this:
Demonstrating method overriding: Generic Animal is eating. Buddy is eating dog food. Demonstrating inherited method: Buddy is sleeping. Dog details: Name: Buddy Age: 3 Breed: Labrador
This demonstrates how method overriding allows the Dog class to provide its own implementation of the eat() method, while still inheriting other methods like sleep() from the Animal class.
Introduction to Polymorphism
Polymorphism is a fundamental concept in object-oriented programming that allows us to use a base class reference to refer to a subclass object. This enables more flexible and reusable code. Let's see how it works.
Create a new file called
Cat.java:touch Cat.javaOpen
Cat.javaand add the following code:public class Cat extends Animal { public Cat(String name, int age) { super(name, age); } @Override public void eat() { System.out.println(getName() + " is eating fish."); } public void meow() { System.out.println(getName() + " says: Meow!"); } }This creates another subclass of
Animalwith its owneat()method and a newmeow()method.Save the
Cat.javafile.Now, let's update our
InheritanceDemo.javato demonstrate polymorphism. Replace its content with:public class InheritanceDemo { public static void main(String[] args) { Animal[] animals = new Animal[3]; animals[0] = new Animal("Generic Animal", 5); animals[1] = new Dog("Buddy", 3, "Labrador"); animals[2] = new Cat("Whiskers", 2); System.out.println("Demonstrating polymorphism:"); for (Animal animal : animals) { animal.eat(); // This will call the appropriate eat() method for each animal } System.out.println("\nAccessing specific methods:"); ((Dog) animals[1]).getBreed(); // We need to cast to Dog to call Dog-specific methods ((Cat) animals[2]).meow(); // We need to cast to Cat to call Cat-specific methods } }This code creates an array of
Animalobjects, but we're actually storing a mix ofAnimal,Dog, andCatobjects in it. When we calleat()on each animal, Java automatically calls the appropriate version of the method based on the actual type of the object.Save the
InheritanceDemo.javafile.Compile and run the updated program:
javac Animal.java Dog.java Cat.java InheritanceDemo.java java InheritanceDemoYou should see output similar to this:
Demonstrating polymorphism: Generic Animal is eating. Buddy is eating dog food. Whiskers is eating fish. Accessing specific methods: Whiskers says: Meow!
This demonstrates polymorphism in action. We're able to treat all the objects as Animal objects, but when we call the eat() method, each object behaves according to its specific class implementation.
Summary
In this lab, we've explored some key concepts of object-oriented programming in Java:
- Inheritance: We created a base
Animalclass and derivedDogandCatclasses from it. This allowed us to reuse code and create a logical hierarchy of classes. - Method Overriding: We saw how subclasses can provide their own implementations of methods defined in the superclass, allowing for more specific behavior.
- Polymorphism: We learned how to treat objects of different classes uniformly through their common superclass, enabling more flexible and reusable code structures.
These concepts are fundamental to Java and object-oriented programming in general. They allow us to create more organized, efficient, and flexible code structures. As you continue your Java journey, you'll find these concepts used extensively in more complex applications.
Remember, practice is key to mastering these concepts.



