Programming Java

Tasks studies - laboratory


Project maintained by dawidolko Hosted on GitHub Pages — Theme by dawidolko

Lab07 - Inheritance and Polymorphism in Java

Task f(-2). Inheritance

Inheritance is one of the fundamental mechanisms of object-oriented programming. This mechanism allows defining new classes based on existing ones.
The word “inheritance” is associated with transferring assets from one person to another in daily life. The analogy in Java is not far from this. Inheritance means that one class inherits methods and variables from another class.
Inheritance in Java is a ubiquitous and powerful mechanism. Almost every class—in fact, every class except java.lang.Object—inherits from another class. Every class implicitly inherits from the mentioned Object class.

What do we inherit from the Object class? Several methods, including the equals(...) method, which checks the equality of objects. This allows us to compare objects of any type with each other using the same method. Another method we inherit from the Object class is toString(). This method returns a textual representation of an object, regardless of its type.

Here’s an example of declaring inheritance and how methods defined in a superclass are inherited by a subclass. First, let’s define a Product class that could describe items we sell in our online store. This class has a method that returns the product price and another method for setting the price when an object is created. Example code:

class Product {
  private double price;
  public double getPrice() {
    return price;
  }
  public void setPrice(double price) {
    this.price = price;
  }
}

A book is a product and, like any product, it has a price. Since a book is a product, it also has all the features of a product. The class describing a book object should therefore inherit from the class describing a product, i.e., the Product class. Example implementation of the class modeling book-type products:

class Book extends Product {
  private int pagesNum;
  public Book(double price, int pagesNum) {
    this.setPrice(price);
    this.pagesNum = pagesNum;
  }
  public int getPagesNum() {
    return pagesNum;
  }
}

Note the extends keyword in the class declaration. This indicates that the Book class inherits from the Product class.
In the Book constructor, we used the inherited setPrice(...) method to set the book price. Furthermore, the Book class inherits not only the methods defined in the Product class, i.e., setPrice(...) and getPrice(), but also the methods inherited by Product from the Object class. Since the Product class does not explicitly inherit from any class, it implicitly inherits from the Object class. Inheritance is transitive, so the methods inherited by the Product class are also passed on to the Book class.

Task f(-1). Method Overriding

Overriding a method involves re-implementing a method inherited from a superclass. This mechanism allows us to adapt method implementations to the specifics of the subclass.
For example, every class inherits the toString() method from the Object class. This method is supposed to return a textual description of an object. By default, it returns the class name and an uninformative hash code. This description is inadequate and should be improved. We can achieve this by overriding the toString() method in our class. In the Book class, the method could be implemented as follows:

class Book extends Product {
  public String toString() {
    return "Book '" + getTitle() + "', ISBN: " + getISBN();
  }
  // Methods getTitle(), getISBN(), and others needed in the Book class
}

Task f(0). Polymorphism

The benefits of inheritance would be very limited without polymorphism. Polymorphism allows objects of different subclasses of a common type to be treated in the same way. Let’s see how this works and how it simplifies programming.
Since a book is a product, in Java, this means that the Book class inherits from the Product class. Therefore, we can treat a book as a product. We can assign an object of type Book to a reference of type Product:

Product myProd = new Book(39.90, 210);

Of course, our store will also sell other items, not just books.
LINK
LINK

We will have classes such as MusicCD, GameCD, and AppCD representing CDs or DVDs with music, games, and applications. All of these classes will inherit from the Product class and can be processed in the system as products. For example:

Product myProd = new MusicCD(19.90, "The Beatles", "A Hard Day's Night");

Then:

myProd.getPrice();

To implement an online store cart that stores selected items and calculates the total order value, we can iterate through the product collection in the cart and call the getPrice() method on each product. The sum of these prices will be the order value.

Polymorphism combined with method overriding can produce even more interesting results. For example, we could define a BonusPackage product representing a bundle of products offered at a promotional price. In the BonusPackage class, we can override the getPrice() method so that it sums up the prices of all products in the package and applies a discount, e.g., 10%.

Introducing a BonusPackage product does not require changes to the cart class or the functionality for calculating the order value. As before, we sum the results of the getPrice() method for each object. For the algorithm, it doesn’t matter that some objects (those of type BonusPackage) have a modified implementation of the getPrice() method.

Task 1.

Implement a class Osoba. This class should store the following values:

name, surname, date of birth, gender and include behaviors such as a method returning information about the person. Next, define classes inheriting from the Osoba class:

  1. Student – the class should include the following:

    a) Fields:

    • student ID
    • type of study
    • field of study
    • year of study

    b) Methods:

    • A method returning information about the student (override the inherited method from the Osoba class). Use the toString() method.
  2. Wykładowca – design this class analogously to the Student class, showcasing creativity.
    LINK

Task 2.

Create a class Punkt2D that stores information describing a point on a 2D plane (coordinates x and y). Include two constructors:

Implement a method that generates random coordinates for a point on the plane in the range of -10 to 10. Override the toString() method to display information about the point’s coordinates.

Next, create a Punkt3D class representing a 3D point, extending the Punkt2D class with an additional field z for the third dimension. Override the coordinate generation method to include the z dimension. Override the toString() method to display information about the 3D point’s coordinates.

In a test class, create objects of both classes and test their functionality. Then create two 100-element arrays:

For all elements in both arrays, generate random points using the previously implemented methods. Check if there are elements in array2D and array3D with matching x and y coordinates (i.e., if there exist points Punkt2D(x1, y1) and Punkt3D(x2, y2, z2) such that x1 = x2 and y1 = y2). If such pairs exist, print them to the screen using the toString() method.