Free response 2 from the 2022 AP Computer Science exam has you working with a class named Book
that contains information about a book, and a subclass Textbook
that extends Book
. You are given the complete Book
class, but have to write Textbook
from scratch.
Since a Textbook
is a Book
, it contains the same information but adds a few things. A Textbook
also has an edition and a method named canSubstituteFor
that determines if a textbook is a valid substitution for another textbook. We also have to override the getBookInfo
method to include the edition.
We’ll need to look at the Book
class even though we’re not changing anything in it.
public class Book {
private String title;
private double price;
public Book(String bookTitle, double bookPrice) {
// Implementation not shown
}
public String getTitle() { return title; }
public String getBookInfo() {
return title + "-" + price;
}
}
We don’t need to worry too much about how these methods work, but since we’re creating a child class we do need to know what methods we have available from the parent.
We weren’t given a shell for this class, so we’re starting with a blank page. That means we need to first define the class.
public class Textbook extends Book {
}
Since Textbook
is inheriting from Book
we need to have Textbook
extend Book
.
Next up is the constructor and any instance variables. We’re given the following two lines as examples.
Textbook bio2015 = new Textbook("Biology", 49.75, 2);
Textbook bio2019 = new Textbook("Biology", 39.75, 3);
This gives us the information we need to implement the constructor and also what instance variables we need to add.
We know that we need a constructor that has parameters for a String
, a double
, and an int
. The notes on the PDF tell us that the String
is the title, the double
is the price, and the int
is the edition.
The title and price are going to be stored in the Book
class. We don’t need instance variables for those. But we do need one for the edition. So let’s go ahead and add in the constructor and the one instance variable that Textbook
needs.
public class Textbook extends Book {
private int edition;
public Textbook(String title, double price, int edition) {
super(title, price);
this.edition = edition;
}
public int getEdition() {
return edition;
}
}
Notice that edition
is private
. Instance variables are almost always private
and they’re always private
on AP exams.
The first line in the constructor sets the instance variables that exist in Book
by calling the Book
constructor. Textbook
is a child class or subclass of Book
, which makes Book
the parent class or super class of Textbook
. So when we use super(title, price);
that calls the constructor in Book
for us.
It’s important that the super
call comes first. If it didn’t, Java would add a super()
call to a no argument constructor to Book
, which doesn’t exist and our code wouldn’t build.
I also went ahead and added the getEdition
method that’s described in the problem instructions.
Next up is the getBookInfo
method which returns a string formatted like this - <book title>-<book price>-<book edition>
.
The catch here is that we don’t have direct access to the title and price from within Textbook
, so we have to ask the super class to give it to us. We could use the getTitle
method that’s inherited to get the title, but we don’t have a way to get the price.
What we do have is a getBookInfo
method in the parent that returns a string <book title>-<book price>
which is almost what we want. But we need to override it to get exactly what we’re after.
public String getBookInfo() {
return super.getBookInfo() + "-" + edition;
}
We want to call the getBookInfo
in Book
, but since we have an overridden version in Textbook
we have to specifically call super.getBookInfo()
for it to work.
And the last method is canSubstituteFor
which compares two Textbook
objects and determines if one can be substituted for the other. A valid substitution is one with the same title and an edition that’s greater than or equal to the other book.
public boolean canSubstituteFor(TextBook other) {
return getTitle().equals(other.getTitle()) && edition >= other.getEdition();
}
We’re doing two things here. First, comparing the title of both this
and other
to see if they match. If they do we also check to see if this.edition
is >=
other.getEdition()
. If both of those statements are true
then the method returns true
, otherwise it returns false
.
And with all of those parts, here’s a full working Textbook
class.
public class TextBook extends Book {
private int edition;
public TextBook(String title, double cost, int ed) {
super(title, cost);
edition = ed;
}
public int getEdition() {
return edition;
}
public String getBookInfo() {
return super.getBookInfo() + "-" + edition;
}
public boolean canSubstituteFor(TextBook other) {
return getTitle().equals(other.getTitle()) && edition >= other.getEdition();
}
}