Edit Page

Lab 1: Object-Oriented Programming Overview

The goal of this lab is to provide you with an overview of fundamental concepts in object-oriented programming, which is a prerequisite to understanding and applying design patterns.

Video

Objectives

In this lab you will

  1. apply fundamental concepts in Object-Oriented Programming.
  2. understand when to use instance and class variables.
  3. write unit tests and apply Test-Driven Development (TDD).
  4. use inheritance appropriately.
  5. effectively utilize inheritance and polymorphism.
  6. apply key object-oriented concepts such as abstraction and encapsulation.

Requirement and Tools

Getting Started

If your instructor is using GitHub classroom, you will need to accept the assignment using the link below, clone the template repository, and import it as a project into your IDE.

If your instructor is not using GitHub classroom, clone and import the template project at https://github.com/cpit252/lab-01.

1. Instance and class variables

Count that does not work

Consider the following Java code:

Product.java

public class Product {
  private int id;
  private double price;
  private String name;
  private int quantity;
  
  public Product(int id, double price, String name){
    this.id = id;
    this.price = price;
    this.name = name;
    this.quantity ++;
  }
  public void applySaleDiscount(double percentage){
    this.price = this.price - ((percentage/100) * this.price);
  }

  public void addToShoppingCart(){
    System.out.println(this.name + " has been added to the shopping cart.");
  }

  public int getTotalQuantity(){
    return this.quantity;
  }
  
  public void getSellableStatus(){
    System.out.println("This product is sellable");
  }

  public String toString(){
    return "Product info:\n+Id: " + this.id + "\t" + "name: " + this.name +
      "\tPrice: SR" + this.price;
  }
}

and the following client program:

App.java

public class App{

  public static void main(String[]args){
    Product p1 = new Product(6745, 5.50, "Penne Pasta");
    Product p2 = new Product(8853, 6.50, "Spaghetti Pasta");
    Product p3 = new Product(2106, 4.50, "Linguine Pasta");
    System.out.println("Total Quantity: " + p3.getTotalQuantity());
  }
}

When compiling this code and running it:

javac *.java
java App

We get the following output:

Total Quantity: 1

Question: How would you fix this code to print the correct total quanitity, 3?


2. Testing

A unit test is a piece of code that executes a specific functionality in the code to be tested and ensures it behaves as intended. This will help you in the future when additional changes are made to the code.

To add Junit 4 to your project, edit the pom.xml file and add the following:

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13.2</version>
        <scope>test</scope>
    </dependency>

Question: Complete the following unit test for the previous problem to ensure that the code always returns the correct quantity.

import org.junit.Test;
import static org.junit.Assert.assertEquals;

public class ProductTest 
{
  @Test
  public void shouldCountQuantity()
  {
    Product p1 = new Product(6745, 5.50, "Penne Pasta");
    Product p2 = new Product(8853, 6.50, "Spaghetti Pasta");
    Product p3 = new Product(2106, 4.50, "Linguine Pasta");
    assertEquals(p3.getTotalQuantity(), 3);
  }

}
Hint: If this is your first time writing tests with JUnit, see writing JUnit Tests in Java under miscellaneous.

3. Inhertiance

Extend the product class by adding the following two derived classes (a.k.a child classes and subclasses):


public class ElectricProduct extends Product{

  private String voltage;

  public ElectricProduct(int id, double price, String name, String voltage){
    super(id, price, name);
    this.voltage = voltage;
  }

  @Override
  public String toString(){
    return super.toString() +"\t Voltage: " + this.voltage;
  }

}
import java.time.LocalDate;

public class FoodProduct extends Product{
  private LocalDate expirationDate;

  public FoodProduct(int id, double price, String name, LocalDate expirationDate){
    super(id, price, name);
    this.expirationDate = expirationDate;
  }

  @Override
  public String toString(){
    return super.toString() +"\t Expiration Date: " + this.expirationDate;
  }
}

And add the following main/client class:

import java.time.LocalDate;

public class App{

  public static void main(String[]args){
    Product p = new Product(1234, 9.99, "water");
    FoodProduct p4 = new FoodProduct(3452, 10.0, "Cheddar Cheese", 
        LocalDate.parse("2022-06-07"));
    ElectricProduct p5 = new ElectricProduct(4875, 30.0, "Extension cord", "220v");
  }
}

Question: The Product class should not be instantiated directly as done in the first line of the main method. Change the Product class, so only concrete classes should be instantiated. What changes would you make?

Hint: You'll need to change the definition of the Product class.

4. Polymorphism “Many Forms”

Question: Change the main class to utilize the use of Polymorphism and iterate through an array of Products using the enhanced for statement (a.k.a For-Each Loop)?

for(Product p: products){
}

5. Controlling Changes

Question: What would you do to prevent subclasses from overriding the addToShoppingCart() method of the Product class without changing its visibility?


6. Abstraction

We decided to add a feature to the Product class by adding Order information:

public class Product {
  private int id;
  private double price;
  private String name;
  private int quantity;
  private int orderId;
  private String orderStatus;
  
  public Product(int id, double price, String name, int orderId, String orderStatus){
    this.id = id;
    this.price = price;
    this.name = name;
    this.orderId = orderId;
    this.orderStatus = "created"
    this.quantity ++;
  }

Question: Why is this considered bad? How would you fix it?


7. Encapsulation

We decided to add a feature to the Product class by adding the product’s weight information. We decided to make it public, so any subclass can change it easily.

public class Product {
  private int id;
  private double price;
  private String name;
  public double weight;
  
  public Product(int id, double price, String name, int orderId, String orderStatus){
    this.id = id;
    this.price = price;
    this.name = name;
    this.orderId = orderId;
    this.orderStatus = "created"
    this.quantity ++;
  }

Question: Why is this considered bad? How would you fix it?

Deliverables and Submission