public class Shape {
protected String name;
private int length;
private int width;
// Default constructor
public Shape() {
this.name = "Shape";
this.length = 11;
this.width = 5;
}
// Parameterized constructor
public Shape(String name, int length, int width) {
this.name = name;
this.length = length;
this.width = width;
}
// Getter methods
public String get_name() {
return this.name;
}
public int get_length() {
return this.length;
}
public int get_width() {
return this.width;
}
// Setter methods
public void set_name(String n) {
this.name = n;
}
public void set_length(int a) {
this.length = a;
}
public void set_width(int b) {
this.width = b;
}
}
Shape s = new Shape();
System.out.println("Name: " + s.get_name());
System.out.println("Length: " + s.get_length());
System.out.println("Width: " + s.get_width());
public class Rectangle extends Shape {
public Rectangle() {
super();
}
public Rectangle(String name, int length, int width) {
super(name, length, width);
}
}
public class Triangle extends Shape {
public Triangle() {
super();
}
public Triangle(String name, int length, int width) {
super(name, length, width);
}
}
Rectangle r = new Rectangle("Rectangle", 10, 5);
System.out.println("Name: " + r.get_name());
System.out.println("Length: " + r.get_length());
System.out.println("Width: " + r.get_width());
Triangle t = new Triangle("Triangle", 10, 5);
System.out.println("Name: " + t.get_name());
System.out.println("Length: " + t.get_length());
System.out.println("Width: " + t.get_width());
Popcorn Hack Here’s a challenge for you: Implement two new subclasses, Circle and Hexagon, extending from the Shape class. Follow the same structure as the Rectangle and Triangle classes!
public class Shape {
protected String name;
private int length;
private int width;
// Default constructor
public Shape() {
this.name = "Shape";
this.length = 11;
this.width = 5;
}
// Parameterized constructor
public Shape(String name, int length, int width) {
this.name = name;
this.length = length;
this.width = width;
}
// Getter methods
public String get_name() {
return this.name;
}
public int get_length() {
return this.length;
}
public int get_width() {
return this.width;
}
// Setter methods
public void set_name(String n) {
this.name = n;
}
public void set_length(int a) {
this.length = a;
}
public void set_width(int b) {
this.width = b;
}
}
Shape s = new Shape();
System.out.println("Name: " + s.get_name());
System.out.println("Length: " + s.get_length());
System.out.println("Width: " + s.get_width());
public class Circle extends Shape {
private int radius;
public Circle() {
super();
this.radius = 5;
}
public Circle(String name, int radius) {
super(name, 0, 0);
this.radius = radius;
}
public int get_radius() {
return this.radius;
}
public void set_radius(int r) {
this.radius = r;
}
}
public class Hexagon extends Shape {
private int side;
public Hexagon() {
super();
this.side = 5;
}
public Hexagon(String name, int side) {
super(name, 0, 0);
this.side = side;
}
public int get_side() {
return this.side;
}
public void set_side(int s) {
this.side = s;
}
}
Circle c = new Circle("Circle", 10);
System.out.println("Name: " + c.get_name());
System.out.println("Radius: " + c.get_radius());
Hexagon h = new Hexagon("Hexagon", 10);
System.out.println("Name: " + h.get_name());
System.out.println("Side: " + h.get_side());
public class Shape {
protected String name;
public int length;
public int width;
// Default constructor
public Shape() {
this.name = "Shape";
this.length = 11;
this.width = 5;
}
// Parameterized constructor
public Shape(String name, int length, int width) {
this.name = name;
this.length = length;
this.width = width;
}
}
public class Rectangle extends Shape {
public Rectangle() {
super();
}
public Rectangle(String name, int length, int width) {
super(name, length, width);
}
}
Rectangle r = new Rectangle("Rectangle", 10, 5);
System.out.println("Name: " + r.name);
System.out.println("Length: " + r.length);
System.out.println("Width: " + r.width);
Name: Rectangle
Length: 10
Width: 5
Popcorn Hack 2 Optional: Mastering super() What if we wanted to understand how to properly use the super() keyword in subclasses to ensure that our shapes are correctly initialized?
Here’s a fun challenge:
Create a new subclass called Ellipse that extends Shape. Constructor: Implement a constructor for Ellipse that accepts parameters for name, length, and width. This constructor should call the superclass constructor using super().
Update Your Driver Code Test the Ellipse: Instantiate an Ellipse object and print its area. Verify that the constructor correctly initializes the shape and that the super() keyword is used properly. Hints:
Ellipse Constructor: Use super(name, length, width) to initialize inherited fields. Check Order: Remember, super() must be the first statement in your subclass constructor.
public class Shape1 {
protected String name;
public int length;
public int width;
public int area;
// Default constructor
public Shape1() {
this.name = "Shape";
this.length = 11;
this.width = 5;
this.area = 0;
}
// Parameterized constructor
public Shape1(String name, int length, int width, int area) {
this.name = name;
this.length = length;
this.width = width;
this.area = area;
}
}
public class Elipsoid extends Shape1 {
public Elipsoid() {
super();
}
public Elipsoid(String name, int length, int width, int area) {
super(name, length, width, area);
}
}
Elipsoid e = new Elipsoid("Elipsoid", 121, 14, 10);
System.out.println("Name: " + e.name);
System.out.println("Length: " + e.length);
System.out.println("Width: " + e.width);
System.out.println("Area: " + e.area);
Name: Elipsoid
Length: 121
Width: 14
Area: 10
Popcorn Hack 1 Lets re-define the Triangle class but this time override the default area method with the Heron’s formula
import java.math.*;
public class Shape {
protected String name;
public int length;
public int width;
// Default constructor
public Shape() {
this.name = "Shape";
this.length = 11;
this.width = 5;
}
// Parameterized constructor
public Shape(String name, int length, int width) {
this.name = name;
this.length = length;
this.width = width;
}
public double calc_area() {
return 0;
}
}
public class Triangle extends Shape {
private int side1;
private int side2;
private int side3;
public Triangle() {
this.name = "triangle";
this.side1 = 1;
this.side2 = 2;
this.side3 = 3;
}
// Constructor that takes a name and three side lengths
public Triangle(String name, int s1, int s2, int s3) {
super(name, 0, 0); // Call to Shape constructor to set the name
this.name = "triangle";
this.side1 = s1;
this.side2 = s2;
this.side3 = s3;
}
@Override
public double calc_area() {
double area = sqrt((side1 + side2 + side3) * (side1 + side2 - side3) * (side1 - side2 + side3) * (-side1 + side2 + side3)) / 4;
//area = sqrt((side1 + side2 + side3) * (side1 + side2 - side3) * (side1 - side2 + side3) * (-side1 + side2 + side3)) / 4;
return area;
//expected output 6
}
}
Triangle t = new Triangle("Triangle", 3, 4, 5);
System.out.println("Name: " + t.name);
System.out.println("Area: " + t.calc_area());
Name: triangle
Area: 6.0
Popcorn Hack 2 re-write the Triangle sublcass so that it also overrides the calc_perimeter()
import static java.lang.Math.sqrt;
public class Shape {
protected String name;
public int length;
public int width;
// Default constructor
public Shape() {
this.name = "Shape";
this.length = 11;
this.width = 5;
}
// Parameterized constructor
public Shape(String name, int length, int width) {
this.name = name;
this.length = length;
this.width = width;
}
public double calc_area() {
return 0;
}
public double calc_perimeter() {
return 0;
}
}
public class Triangle extends Shape {
public int side1;
public int side2;
public int side3;
public Triangle() {
this.name = "triangle";
this.side1 = 1;
this.side2 = 2;
this.side3 = 3;
}
// Constructor that takes a name and three side lengths
public Triangle(String name, int s1, int s2, int s3) {
super(name, 0, 0); // Call to Shape constructor to set the name
this.name = "triangle";
this.side1 = s1;
this.side2 = s2;
this.side3 = s3;
}
@Override
public double calc_area() {
// Calculate the semi-perimeter
double s = (side1 + side2 + side3) / 2.0;
// Use Heron's formula to calculate the area
double area = sqrt(s * (s - side1) * (s - side2) * (s - side3));
return area;
}
@Override
public double calc_perimeter() {
return side1 + side2 + side3;
}
public String get_name() {
return this.name;
}
}
Triangle t = new Triangle("Triangle", 3, 4, 5);
System.out.println("Name: " + t.get_name());
System.out.println("Side1: " + t.side1);
System.out.println("Side2: " + t.side2);
System.out.println("Side3: " + t.side3);
System.out.println("Area: " + t.calc_area());
System.out.println("Perimeter: " + t.calc_perimeter());
Name: triangle
Side1: 3
Side2: 4
Side3: 5
Area: 6.0
Perimeter: 12.0
class Shape {
public String draw() {
return "Drawing a shape";
}
}
class Triangle extends Shape {
@Override
public String draw() {
return "Drawing a triangle";
}
}
Shape myTriangle = new Triangle();
System.out.println(myTriangle.draw()); // Should output: "Drawing a triangle."
Drawing a triangle
class Shape {
public String draw() {
return "Drawing a shape";
}
}
class Rectangle extends Shape {
@Override
public String draw() {
return "Drawing a rectangle";
}
}
Shape myRectangle = new Rectangle();
System.out.println(myRectangle.draw()); // Should output: "Drawing a rectangle."
Drawing a rectangle
class Shape {
public String draw() {
return "Drawing a shape";
}
public double area() {
return 0; // Default implementation
}
}
class Circle extends Shape {
double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
public double area() {
return Math.PI * radius * radius;
}
}
class Square extends Shape {
double side;
public Square(double side) {
this.side = side;
}
@Override
public double area() {
return side * side;
}
}
class Triangle extends Shape {
double side1, side2, side3;
public Triangle(double side1, double side2, double side3) {
this.side1 = side1;
this.side2 = side2;
this.side3 = side3;
}
@Override
public double area() {
double s = (side1 + side2 + side3) / 2.0;
return Math.sqrt(s * (s - side1) * (s - side2) * (s - side3));
}
}
class Rectangle extends Shape {
double length, width;
public Rectangle(double length, double width) {
this.length = length;
this.width = width;
}
@Override
public double area() {
return length * width;
}
}
Circle c = new Circle(5);
System.out.println("Circle Area: " + c.area());
Square s = new Square(4);
System.out.println("Square Area: " + s.area());
Triangle t = new Triangle(3, 4, 5);
System.out.println("Triangle Area: " + t.area());
Rectangle r = new Rectangle(4, 5);
System.out.println("Rectangle Area: " + r.area());
Circle Area: 78.53981633974483
Square Area: 16.0
Triangle Area: 6.0
Rectangle Area: 20.0
Homework Hack For your homework, create your own class hierarchy for shapes. You should have a base class called Shape with subclasses Triangle, Rectangle, and Hexagon. Each subclass should implement a method called draw(), returning a unique string for each shape type.
-
Triangle
: "Drawing a triangle." -
Rectangle
: "Drawing a rectangle." -
Hexagon
: "Drawing a hexagon." Make sure to demonstrate polymorphism by creating an array of Shape types and iterating through it to call the draw() method. This will reinforce your understanding of class hierarchies and method overriding.
// Base class
class Shape {
public String draw() {
return "Drawing a shape";
}
}
// Subclass Triangle
class Triangle extends Shape {
@Override
public String draw() {
return "Drawing a triangle.";
}
}
// Subclass Rectangle
class Rectangle extends Shape {
@Override
public String draw() {
return "Drawing a rectangle.";
}
}
// Subclass Hexagon
class Hexagon extends Shape {
@Override
public String draw() {
return "Drawing a hexagon.";
}
}
// Create an array of Shape types
Shape[] shapes = new Shape[3];
shapes[0] = new Triangle();
shapes[1] = new Rectangle();
shapes[2] = new Hexagon();
// Iterate through the array and call the draw() method
for (Shape shape : shapes) {
System.out.println(shape.draw());
}
Drawing a triangle.
Drawing a rectangle.
Drawing a hexagon.
Popcorn Hacks Create an example of Polymorphism in your own project. If you want some more information and examples of Polymorphism see the examples further down
class Shape {
public void draw() {
System.out.println("Drawing a shape");
}
}
class Circle extends Shape {
@Override
public void draw() {
System.out.println("Drawing a circle");
}
}
class Square extends Shape {
@Override
public void draw() {
System.out.println("Drawing a square");
}
}
class Triangle extends Shape {
@Override
public void draw() {
System.out.println("Drawing a triangle");
}
}
class Rectangle extends Shape {
@Override
public void draw() {
System.out.println("Drawing a rectangle");
}
}
Shape[] shapes = {new Circle(), new Square(), new Triangle(), new Rectangle()};
for (Shape shape : shapes) {
shape.draw();
}
Drawing a circle
Drawing a square
Drawing a triangle
Drawing a rectangle
class Shape {
String getName(){
return "Shape";
}
}
class Square extends Shape{
@Override
String getName(){
return "Square";
}
}
Shape myShape = new Square();
System.out.println(myShape.getName()); // Should output: "Square"
Square
Popcorn Hacks Using your previous polymorphism example, explain which parts are the static types and which are the dynamic types
// Base class
class Shape {
// Method to draw a shape
public void draw() {
System.out.println("Drawing a shape");
}
}
// Subclass Circle
class Circle extends Shape {
// Overriding the draw method to draw a circle
@Override
public void draw() {
System.out.println("Drawing a circle");
}
}
// Subclass Square
class Square extends Shape {
// Overriding the draw method to draw a square
@Override
public void draw() {
System.out.println("Drawing a square");
}
}
// Subclass Triangle
class Triangle extends Shape {
// Overriding the draw method to draw a triangle
@Override
public void draw() {
System.out.println("Drawing a triangle");
}
}
// Subclass Rectangle
class Rectangle extends Shape {
// Overriding the draw method to draw a rectangle
@Override
public void draw() {
System.out.println("Drawing a rectangle");
}
}
// Creating an array of Shape types
Shape[] shapes = {new Circle(), new Square(), new Triangle(), new Rectangle()};
// Iterating through the array and calling the draw() method
for (Shape shape : shapes) {
shape.draw();
}
Drawing a circle
Drawing a square
Drawing a triangle
Drawing a rectangle
class Shape {
String getName(){
return "Shape";
}
}
class Square extends Shape{
@Override
String getName(){
return "Square";
}
int getSides(){
return 4;
}
}
Shape myShape = new Square(); //this does not have access to the Sqaure methods despite referencing a sqaure
Square mySquare = (Square)myShape; //down-cast the Shape to a Sqaure to run the Sqaure specific methods
System.out.println(mySquare.getSides());//after down-casting you can now run the Square methods
4
Popcorn Hacks Define down-casting in your own words add an example of down-casting to your previous polymorphism example
Downcasting: Downcasting is the process of casting a reference of a base class to one of its derived classes. It is done by putting the type in parentheses in front of the object. Downcasting is used when a reference of a base class refers to an object of a derived class.
// Base class
class Shape {
// Method to draw a shape
public void draw() {
System.out.println("Drawing a shape");
}
}
// Subclass Circle
class Circle extends Shape {
// Overriding the draw method to draw a circle
@Override
public void draw() {
System.out.println("Drawing a circle");
}
// Method specific to Circle
public void specificCircleMethod() {
System.out.println("Specific method for Circle");
}
}
// Subclass Square
class Square extends Shape {
// Overriding the draw method to draw a square
@Override
public void draw() {
System.out.println("Drawing a square");
}
}
// Subclass Triangle
class Triangle extends Shape {
// Overriding the draw method to draw a triangle
@Override
public void draw() {
System.out.println("Drawing a triangle");
}
}
// Subclass Rectangle
class Rectangle extends Shape {
// Overriding the draw method to draw a rectangle
@Override
public void draw() {
System.out.println("Drawing a rectangle");
}
}
// Creating an array of Shape types
Shape[] shapes = {new Circle(), new Square(), new Triangle(), new Rectangle()};
// Iterating through the array and calling the draw() method
for (Shape shape : shapes) {
shape.draw();
// Down-casting to Circle to call specificCircleMethod
if (shape instanceof Circle) {
Circle circle = (Circle) shape;
circle.specificCircleMethod();
}
}
Drawing a circle
Specific method for Circle
Drawing a square
Drawing a triangle
Drawing a rectangle
Popcorn Hacks Create an example where you execute an unchanged method from Object, then execute a different method from Object that you changed.
class CustomClass {
private int id;
private String name;
public CustomClass(int id, String name) {
this.id = id;
this.name = name;
}
// Overriding the toString() method from Object class
@Override
public String toString() {
return "CustomClass{id=" + id + ", name='" + name + "'}";
}
// Using the hashCode() method from Object class unchanged
}
CustomClass obj = new CustomClass(1, "Example");
// Executing the unchanged hashCode() method from Object class
int hashCode = obj.hashCode();
System.out.println("HashCode: " + hashCode);
// Executing the overridden toString() method from Object class
String str = obj.toString();
System.out.println("ToString: " + str);
HashCode: 1701100541
ToString: CustomClass{id=1, name='Example'}
FRQ Prompt Consider a program that manages a collection of books, specifically focusing on textbooks. You are required to implement a class named Textbook that extends an existing class called Book. The Textbook class should include the following features:
- A private integer field named edition that represents the edition number of the textbook.
- A constructor that takes three parameters: a string for the title, a double for the price, and an integer for the edition. This constructor should invoke the superclass constructor to initialize the title and price.
- A method getEdition() that returns the edition of the textbook.
- A method canSubstituteFor(Textbook other) that determines if the current textbook can be substituted for another textbook. This method should return true if both textbooks have the same title and the current textbook’s edition is equal to or greater than the other textbook’s edition.
- An overridden method getBookInfo() that returns a string representation of the textbook information, including the title, price, and edition.
- Optional: Include error handling in the constructor to ensure that the edition is a positive integer, and override the toString() method for convenient output of the textbook information. Write the complete implementation of the Textbook class, including all specified methods and any additional features you believe would be beneficial.
// Assuming the Book class is defined as follows:
class Book {
private String title;
private double price;
public Book(String title, double price) {
this.title = title;
this.price = price;
}
public String getTitle() {
return title;
}
public double getPrice() {
return price;
}
public String getBookInfo() {
return "Title: " + title + ", Price: " + price;
}
}
// Textbook class extending Book
class Textbook extends Book {
private int edition;
public Textbook(String title, double price, int edition) {
super(title, price);
if (edition <= 0) {
throw new IllegalArgumentException("Edition must be a positive integer.");
}
this.edition = edition;
}
public int getEdition() {
return edition;
}
public boolean canSubstituteFor(Textbook other) {
return this.getTitle().equals(other.getTitle()) && this.edition >= other.getEdition();
}
@Override
public String getBookInfo() {
return super.getBookInfo() + ", Edition: " + edition;
}
@Override
public String toString() {
return "Textbook{" +
"title='" + getTitle() + '\'' +
", price=" + getPrice() +
", edition=" + edition +
'}';
}
}
Textbook textbook1 = new Textbook("Java Programming", 59.99, 3);
Textbook textbook2 = new Textbook("Java Programming", 59.99, 2);
System.out.println(textbook1.getBookInfo());
System.out.println(textbook2.getBookInfo());
System.out.println("Can textbook1 substitute for textbook2? " + textbook1.canSubstituteFor(textbook2));
System.out.println("Can textbook2 substitute for textbook1? " + textbook2.canSubstituteFor(textbook1));
System.out.println(textbook1);
System.out.println(textbook2);
Title: Java Programming, Price: 59.99, Edition: 3
Title: Java Programming, Price: 59.99, Edition: 2
Can textbook1 substitute for textbook2? true
Can textbook2 substitute for textbook1? false
Textbook{title='Java Programming', price=59.99, edition=3}
Textbook{title='Java Programming', price=59.99, edition=2}
abstract class Shape {
public abstract double area();
public abstract double calc_perimeter();
public void print_something() {
System.out.println("This is a shape");
}
}
class Ellipse extends Shape {
private double majorAxis;
private double minorAxis;
public Ellipse(double majorAxis, double minorAxis) {
this.majorAxis = majorAxis;
this.minorAxis = minorAxis;
}
@Override
public double area() {
return Math.PI * majorAxis * minorAxis;
}
@Override
public double calc_perimeter() {
return 2 * Math.PI * Math.sqrt((majorAxis * majorAxis + minorAxis * minorAxis) / 2);
}
@Override
public void print_something() {
super.print_something();
System.out.println("and also an ellipse");
}
}
class Hexagon extends Shape {
private double side;
public Hexagon(double side) {
this.side = side;
}
@Override
public double area() {
return (3 * Math.sqrt(3) / 2) * side * side;
}
@Override
public double calc_perimeter() {
return 6 * side;
}
@Override
public void print_something() {
super.print_something();
System.out.println("and also a hexagon");
}
}
Shape ellipse = new Ellipse(5, 3);
Shape hexagon = new Hexagon(4);
System.out.println("Ellipse Area: " + ellipse.area());
System.out.println("Ellipse Perimeter: " + ellipse.calc_perimeter());
ellipse.print_something();
System.out.println("Hexagon Area: " + hexagon.area());
System.out.println("Hexagon Perimeter: " + hexagon.calc_perimeter());
hexagon.print_something();
Ellipse Area: 47.12388980384689
Ellipse Perimeter: 25.90623668683038
This is a shape
and also an ellipse
Hexagon Area: 41.569219381653056
Hexagon Perimeter: 24.0
This is a shape
and also a hexagon
Multiple Choice
-
What is wrong with this block of code? class Shape{ private double length = 0; private double width = 0;
public Shape(double length, double width){ this.length = length; this.width = width; }
public double getArea(){ return this.length * this.width; }
private String toString(){ return "Shape length:"+ (new Double(this.length)).toString() + " width:" + (new Double(this.width)).toString(); } }
Shape myShape = new Shape(2,3);
System.out.println(myShape.getArea()); a) You can’t use the this keyword in the constructor
b) When passing a double through an argument it must be in the form of 0.0
c) The toString() method must be public
d) The getArea() method doesn’t return a double
Answer: c) The toString() method must be public
-
Which method cannot be exectuted in the following example of Polymorphism class Water{ public String toString(){ return "Water"; }
private boolean isSalty(){ return false; }
public String typeOfWater(){ return "Static"; }
}
class Lake extends Water{ public String toString(){ return "Lake"; }
public boolean isSalty(){
return true;
}
}
Water myLakeWater = new Lake(); a) typeOfWater()
b) isSalty()
c) toString()
d) getClass()
Answer: a) typeOfWater()