IBDP Computer Science B3.1 Fundamentals of OOP for a single class HL Paper 2 - New Syllabus
Question
An invoice is created every time a customer purchases one or more products.
The Invoice class keeps details of each invoice. The following shows part of the code for this class:
public class Invoice {
private String invoiceID; // identifies a unique invoice
private static Product[] products = new Product[20]; // list of
// products purchased
private static int[] prodQuantity = new int[20]; // number of items
// of a particular product purchased
private boolean qualifiesForDiscount; // default value is false
private int numOfProducts; // how many products in this invoice
// constructor is defined, code not shown
public String getInvoiceID(){
return invoiceID;
}
// all accessor and mutator methods are present but not shown
public void addProduct(Product product, int quantity) {
// code missing
}
public void setQualifiesForDiscount() {
// if total value of purchases is more than 3000,
// qualifiesForDiscount value is set to true
// code missing
}
} // end of Invoice classaddProduct(Product product, int quantity) that will update an invoice.The method should:
- Update the
productsarray - Update the
prodQuantityarray - Increment the
numOfProducts.
If the total value of the purchases is greater than 3000, the invoice qualifies for a discount.
setQualifiesForDiscount() to change the status of an invoice.The method should:
- calculate the total value of an invoice
- change the value of
qualifiesForDiscountif needed.
Most-appropriate topic code
▶️ Answer/Explanation
(a) (i)
For the correct answer:
Code reusability: polymorphism allows a method or function to work with objects of different classes that share a common interface or base class. This allows developers to write more general and reusable code.
Another valid advantage is that polymorphism can simplify code by reducing the need for multiple if–else or switch statements, because the appropriate method can be selected at runtime.
(a) (ii)
For the correct answer:
Data hiding and protection: encapsulation hides internal data from outside interference or misuse. Access to the data can be controlled through methods such as getters and setters, allowing validation to be applied where required.
(a) (iii)
For the correct answer:
Tight coupling: a child class is tightly coupled to its parent class. A change in the parent class can unintentionally affect the child class and potentially introduce errors.
Another valid disadvantage is that deep inheritance hierarchies can increase complexity, making code harder to understand, debug, and maintain.
(b)
For the correct answer:
- The
Invoiceclass bundles the variables and methods together into a single unit, with the methods operating on the variables to manage access and updates. - The variables in the
Invoiceclass are declaredprivate, preventing direct access from outside the class. Methods such asgetInvoiceID()andsetQualifiesForDiscount()provide controlled access to the object’s data.
Explanation: The private attributes hide the internal state of the invoice, while public methods provide controlled ways of accessing or modifying that state.
(c)
For the correct answer:
public void addProduct(Product product, int quantity)
{
products[numOfProducts] = product;
prodQuantity[numOfProducts] = quantity;
numOfProducts += 1;
}The method stores the supplied Product object in the products array, stores its corresponding quantity in the prodQuantity array, and then increments numOfProducts.
An alternative solution that searches for the next available null position is also valid:
public void addProduct(Product product, int quantity)
{
boolean added = false;
for (int i = 0; i < products.length && !added; i++)
{
if (products[i] == null)
{
products[i] = product;
prodQuantity[i] = quantity;
numOfProducts += 1;
added = true;
}
}
}Note: The candidate is not required to check whether the products[] array is full.
(d)
For the correct answer:
public void setQualifiesForDiscount()
{
float totalValue = 0;
for (int i = 0; i < numOfProducts; i++)
{
float price = products[i].getProdBrand().getBrandPrice();
float amount = price * prodQuantity[i];
totalValue = totalValue + amount;
}
if (totalValue > 3000)
{
qualifiesForDiscount = true;
}
}Explanation:
totalValueis initialized to zero.- The loop processes each product in the invoice up to
numOfProducts. - The product’s brand price is obtained using
getProdBrand().getBrandPrice(). - The price is multiplied by the corresponding quantity in
prodQuantity[]. - Each amount is added to
totalValue. - If the final total is greater than 3000,
qualifiesForDiscountis set totrue.
(e)
For the correct answer:
Easier and faster debugging: smaller individual modules contain fewer possible sources of error, making it easier to locate and correct mistakes in the program.
Other valid advantages include faster project completion because different teams can work on separate modules simultaneously, improved code reusability, better code organization, and reduced coupling between modules.
