I am trying to use a loop to traverse an Arraylist of objects, but when I call abstract methods to be printed I get the symbol cannot be found error For example:
ArrayList<Shape> al = new ArrayList<Shape>();
Shape triangle = new Triangle(3.0, 2.5, 2.0);
Shape rectangle = new Rectangle(2.0, 4.0);
Shape circle = new Circle(1.0);
al.add(triangle);
al.add(rectangle);
al.add(circle);
for(int i = 0; i < al.size(); i++)
{
System.out.println(al.get(i), al.calculateArea(), al.calculatePerimeter(), al.toString());
}
}
Full rectangle class
public class Rectangle extends Shape
{
private double length, width;
public Rectangle(double length, double width)
{
double length1 = length;
double width1 = width;
}
public double calculateArea()
{
double rectangleArea = length * width;
return rectangleArea;
}
public double calculatePerimeter()
{
double rectanglePerimeter = (length * 2) + (width * 2);
return rectanglePerimeter;
}
public String toString()
{
// put your code here
return super.toString() + "[length=" + length + "width=" + width + "]";
}
toString() and get(i) seem to work fine, but in calling the abstract methods implemented in triangle, circle etc subclasses the symbol error comes up. I tried overriding these methods in the subclasses but I get the same error.
Here:
al.calculateArea()
You invoke the methods on your list al, not on a List element!
And of course, the List itself doesn't know anything about the methods your list elements provide! Because the list object is of type List (respectively ArrayList). A List is not a Shape, thus you can't call Shape methods on the list.
You need
al.get(i).calculateArea()
for example! Or even simpler:
for (Shape aShape : al) {
shape.calculateArea();...
In other words: you don't pay with your wallet, you pay by fetching your money out of the wallet, and then you pay with that money!
Related
I was working on a project that involves using abstract classes and methods. The idea is we have general abstract class Shape and three subclasses Circle, Triangle, and Rectangle. I have to calculate the area of each shape, so I defined an abstract method in the Shape class: calculateArea() that returns the area of a shape. Each subclass overrides this method and calculates its area respectively. I have a tester class DrawingApp that instantiates an array of 10 random shapes and computes the total area of the shapes. Now I looked over my code and the logic seems to be correct. In the DrawingApp class, I instantiate 10 different objects of type Shape using a for-loop and a random number between 1 and 3 is generated, if the number is 1 then we instantiate a Circle and vice versa (2 would be a Rectangle and 3 for Triangle). Now I think this seems to be correct but after instantiating 10 random objects, I would like to print out the area of each different shape. So I used a for loop to iterate over the 10 objects that were created and call: System.out.println(randomShapes[i]). Now the problem I face is when iterating over the 10 Shapes, it prints null 10 times instead of printing the area of each shape. I looked over my code multiple times but cannot figure out why it is doing this. Is it a NullPointerException error? I'm really confused and any help would be very helpful. Thank you. Also Below I listed the following classes: DrawingApp.java, Shape.java, and Circle.java. I did not list the other classes (Rectangle and Triangle) because it does the same thing as Circle.java and the only difference is the formula.
DrawingApp.java
class DrawingApp {
public static void main(String[] args) {
Shape [] randomShapes = new Shape[10]; // an array of 10 random shapes: Circle, Triangle or Rectangle
// create 10 random shapes
for(int i = 0; i < randomShapes.length; i++) {
double randomNumber = Math.random() * (3 - 1 + 1) + 1; // generates a random between 1 and 3
// circle
if(randomNumber == 1) {
double circleRadius = Math.random() * (10 - 1 + 1) + 1; // generates a random between 1 and 10
randomShapes[i] = new Circle("Circle", circleRadius);
}
// rectangle
else if(randomNumber == 2) {
double length = Math.random() * (10 - 1 + 1) + 1; // generates a random between 1 and 10
double width = Math.random() * (10 - 1 + 1) + 1; // generates a random between 1 and 10
randomShapes[i] = new Rectangle("Rectangle", length, width);
}
// triangle
else if(randomNumber == 3) {
double height = Math.random() * (10 - 1 + 1) + 1; // generates a random between 1 and 10
double base = Math.random() * (10 - 1 + 1) + 1; // generates a random between 1 and 10
randomShapes[i] = new Triangle("Triangle", height, base);
}
}
// prints null instead of area of that shape
for(int i = 0; i < randomShapes.length; i++){
System.out.println(randomShapes[i]); // call toString and display shape name, id, and area
}
}
}
Shape.java
abstract class Shape {
protected static int id = 0; // id for each shape
protected String label; // the shape label
public Shape(String label) {
id++;
this.label = label;
}
public abstract double calculateArea(); // abstract method for calculating the area of a shape
// getters and setters
public static int getId() {
return id;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
}
Circle.java
class Circle extends Shape {
private double radius;
public Circle(String label, double radius) {
super(label);
this.radius = radius;
}
#Override
public double calculateArea() {
double area = Math.PI * Math.pow(radius, 2);
return area;
}
#Override
public String toString() {
return "Id = " + super.getId() + ". Shape = " + super.getLabel() + ". Area = " + this.calculateArea();
}
}
Output (disclaimer: The circle points do not get printed. It just a list for StackOverflow.
null
null
null
null
null
null
null
null
null
null
I've looked up the "interface" function several places, but nowhere does it seem to actually explain the benefits of using it, or why I should use interfaces when writing my own future programs.
I finished the exercise below, where I used an interface named "Form" to describe the methods "circumference" and "area". Then I have 3 classes "Circle", "Rectangle" and "Square" where the variables from each form are input and calculated to finally retrieve the circumference and area of each form.
My problem is that after I finished the exercise, I'm struggling to really see the point of implementing this "Form" interface. I feel like I could have just ignored using an interface and then simply through inheritance, make each of the classes inherit the circumference and area methods and then just create objects for each of the forms at the end when compiling?
How did the interface make things easier for me?
public class FormCompiling {
public static void main(String[] args) {
Form[] f = {new Circle(1.5), new Rectangle(2.0,3.0), new Square(2.5)};
System.out.println("Area:");
for(int i = 0 ; i<f.length; i++) {
System.out.println(f[i].area());
}
}
}
public interface Form {
public double circumference();
public double area();
}
public class Circle implements Form {
double radius = 0;
double area = 0;
double circumference = 0;
Circle(double radius) {
this.radius = radius;
}
#Override
public double circumference() {
circumference = 2 * radius * Math.PI;
return circumference;
}
#Override
public double area() {
area = radius * radius * Math.PI;
return area;
}
}
public class Rectangle implements Form {
double length = 0;
double width = 0;
double area = 0;
double circumference = 0;
Rectangle(double length, double width) {
this.length = length;
this.width = width;
}
#Override
public double circumference() {
circumference = (2 * length) + (2 * width);
return circumference;
}
#Override
public double area() {
area = length * width;
return area;
}
}
public class Square extends Rectangle implements Form {
Square(double length) {
super(length, length);
this.length = length;
}
#Override
public double circumference() {
circumference = 4 * length;
return circumference;
}
#Override
public double area() {
area = length * length;
return area;
}
}
Yes, you could have a parent class with empty methods (or some of them implemented).. and you'd get a similar result. However, you would not get compile errors if you forgot to implement some of the methods.
An interface "forces" you to follow some contract; a parent class does not.
In fact, an interface is a contract.
Whoever decides to implement it, has to implement the contract.
interface = the "what" = contract = specification
class = the "how" = implementation
The biggest use case for interfaces in Java is to facilitate Polymorphism. Polymorphism means having a single class behave like multiple other classes. Multiple inheritance is not supported in Java so you can't extend more than one class, but you can implement multiple interfaces. There are many useful docs about this topic, here is an official one from oracle to get you started: https://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html
Interfaces are also useful as a "social contract" between a designer of a class/program and the developer who implements it. By implementing an interface you promise that your implementation follows specific behaviors. This allows for consistency amongst different implementations, which is especially useful when trying to collaborate with many developers on a single, large project.
I have created a list of Objects and added elements such as Circle and Square in it. I have added a method in the sqaure and circle classes which checks the instance of the object and compares the area.
public class Circle extends Shape implements Comparable <Object>{
public int compareTo(Object otherObject) {
double difference=0.0;
int retValue= 3;
if(otherObject instanceof Circle){
Circle circle= (Circle)otherObject;
difference= this.area()- circle.area(); //calculate the difference of areas
}
if(otherObject instanceof Square){
Square square= (Square)otherObject; //Casting the object to Sqaure
difference= this.area()- square.area();//Calculate difference of Areaareas
}
if(difference == 0.0)retValue = 0; //return 0 if area is equal
if(difference < Shape.TOLERANCE)retValue = -1; //return -1 if area of the circle is less than the otherObject
if(difference > Shape.TOLERANCE)retValue = 1; //return 1 if area of the circle is more than the otherObject
return retValue;
}
}
My class where I want to sort this looks like this:-
List<Object> objectList = new ArrayList<Object>();
when, I am trying Collections.sort(objectList), it is giving me an me error
no suitable method found for sort(List<Object>)
Any suggestions. Also I have declared my class like
Apples vs. Oranges, or in your case Circles vs. Squares.
You need to make them share a common aspect, which means that you need to make them implement a Shape2D interface with a double getArea() method.
You can then write a Comparator<Shape2D> and call sort(myShapeList, myAreaComparator).
Update
Given the extra code now shown in question, you already have the common base class Shape, which appears to have an abstract double area() method, implemented by both Circle and Square.
You then change Shape to be Comparable<Shape> (not Object), and the compareTo() method, which now takes a Shape as parameter, can call area() without any casting.
It doesn't make sense for a Circle to be comparable to Object.
If you want to sort circles and squares by their area,
use a Comparator instead.
It will also make sense to:
Use a List<Shape> rather than a List<Object>
A Comparator<Shape> can do the job, using Shape.area for the ordering
Use Double.compare to compare the areas, instead of manual if-else
Something like this:
public void demo() {
List<Shape> shapes = new ArrayList<>();
shapes.add(new Circle(2));
shapes.add(new Square(2));
shapes.add(new Square(1));
shapes.add(new Circle(1));
Collections.sort(shapes, new Comparator<Shape>() {
#Override
public int compare(Shape o1, Shape o2) {
return Double.compare(o1.area(), o2.area());
}
});
System.out.println(shapes);
}
Where the implementation of Shape, Circle, Square can be simple like this:
abstract class Shape {
abstract double area();
}
class Circle extends Shape {
private final double radius;
Circle(double radius) {
this.radius = radius;
}
#Override
double area() {
return radius * radius * Math.PI;
}
#Override
public String toString() {
return "Circle(" + radius + ")";
}
}
class Square extends Shape {
private final double side;
Square(double side) {
this.side = side;
}
#Override
double area() {
return side * side;
}
#Override
public String toString() {
return "Square(" + side + ")";
}
}
I have been assigned the following task for an introductory java course:
You should write a class that represents a circle object and includes the following:
Private class variables that store the radius and centre coordinates of the object.
Constructors to create circle objects with nothing supplied, with just a radius value supplied and with a radius and centre coordinates supplied.
Public instance methods that allow the radius and centre coordinates to be set and retrieved (often known as set/get methods).
Public instance methods that return the circumference and area of the circle.
A public class method that tests if two circle objects overlap or not
Here is my code:
import java.lang.Math;
public class Circle {
private double xCentre, yCentre, Radius;
// constructors
public Circle() {
xCentre = 0.0;
yCentre = 0.0;
Radius = 1.0;
}
public Circle(double R) {
xCentre = 0.0;
yCentre = 0.0;
Radius = R;
}
public Circle(double x, double y, double R) {
xCentre = x;
yCentre = y;
Radius = R;
}
//getters
public double getX() {
return xCentre;
}
public double getY() {
return yCentre;
}
public double getRadius() {
return Radius;
}
//setters
public void setX(double NewX) {
xCentre = NewX;
}
public void setY(double NewY) {
yCentre = NewY;
}
public void setRadius(double NewR) {
Radius = NewR;
}
//calculate circumference and area
public double Circumference() {
return 2*Math.PI*Radius;
}
public double Area() {
return Math.PI*Radius*Radius;
}
//determine overlap
public static double Overlap(Circle c1, Circle c2) {
double xDelta = c1.getX() - c2.getX();
double yDelta = c1.getY() - c2.getY();
double separation = Math.sqrt(xDelta*xDelta + yDelta*yDelta);
double radii = c1.getRadius() + c2.getRadius();
return separation - radii;
}
}
}
and
import java.io.Console;
public class cp6 {
public static void main(String args[]){
//Set up the Console
Console myConsole = System.console();
//Declare cirlce
Circle first = new Circle(2.0,4.0,6.0);
myConsole.printf("Circumference of first circle is ", first.Circumference(), "\n");
myConsole.printf("Area of first circle is ", first.Circumference(), "/n");
first.setRadius(2);
first.setX(2);
first.setY(2);
myConsole.printf("New X of first circle is ", first.getX(), "/n");
myConsole.printf("New Y of first circle is ", first.getY(), "/n");
myConsole.printf("New Radius of first circle is ", first.getRadius(), "/n");
Circle second = new Circle(-1.0,3.0,5.0);
Circle third = new Circle(1,1,1);
if (Circle.Overlap(second, third) <= 0) {
myConsole.printf("Second and third circles overlap");
}
else {
myConsole.printf("Second and third circles do not overlap");
}
myConsole.printf("New Y of first circle is ", first.getY());
Calculate and print out distance between them using the class method
myConsole.printf("Distance between first and second is : %.5g\n", Circle.Overlap(first, second));
}
}
The second program just has to demonstrate each aspect addressed in the brief I pasted at the top and I've only a rough idea of how to do this so if what I'm doing seems stupid to any of you please offer suggestions of what else I can do.
Your problem is that you're using the Console.printf() method incorrectly.
The first parameter to this method should be a format, and it has to have placeholders inside it for the other parameters. Read up on it in The Java Platform documentation. In fact, you should familiarize yourself with the Java platform documentation. You need to use it often to make sure you're calling methods correctly or what methods are available in a given class.
So, your printout lines should actually have been:
myConsole.printf("Circumference of first circle is %.2f%n", first.Circumference());
myConsole.printf("Area of first circle is %.2f%n", first.Area());
...etc.
The format %.2f means "The corresponding parameter is a floating-point number. Display it with a precision of 2 digits after the decimal point". The %n replaces your "\n" - the whole "template" of the print should be just in the format string. And in this type of format, one should use %n instead of \n.
I'm not sure why you opted for using the system console rather than the usual System.out.println(). If you choose to go with System.out, there is also a printf() method there that works exactly as Console.printf() - the first parameter is a format, the others are embedded in it.
One last comment: there are conventions when writing Java code:
Indent your code properly
Class names' first letter is always uppercase.
Non-constant fields and local variable names' first letter is always lowercase.
Method names also start with a lowercase letter.
So a section of my assignment is to make a triangle class to be linked to various buttons...but I'm not sure how to make one in eclipse. The specific instructions say this:
Create a triangle class
Data fields: Point[] coords;
constructors
Implement all abstract methods defined in superclass
Getters and setters for each data field
Override public void paint(Graphics arg0) method
I have everything set up in the other classes..except for the triangle class. I'm confused on how to create a triangle using an array of points...Do I need to use Point x,y or somehow store 3 (x,y) coordinate pairs in that one array variable coords? I imagine to create it you would use drawPolygon...but I'm not certain. Any tips?
Here is an example class for Triangle
public class Triangle {
private Point[] coords;
// Null object constructor
public Triangle() {
this.coords = null;
}
// Constructor with point array
public Triangle(Point[] coords) {
this.coords = coords;
}
// Constructor with multiple points
public Triangle(Point a, Point b, Point c) {
this.coords = new Point[3];
coords[0] = a;
coords[1] = b;
coords[2] = c;
}
// The actual paint method
public void paint(Graphics arg0) {
// Setup local variables to hold the coordinates
int[] x = new int[3];
int[] y = new int[3];
// Loop through our points
for (int i = 0; i < coords.length; i++) {
Point point = coords[i];
// Parse out the coordinates as integers and store to our local variables
x[i] = Double.valueOf(point.getX()).intValue();
y[i] = Double.valueOf(point.getY()).intValue();
}
// Actually commit to our polygon
arg0.drawPolygon(x, y, 3);
}
}
Not sure what exactly this class is supposed to be extending, so nothing is marked as an override or anything, and it is missing setters and accessors, but you should be able to make it work.
Use the g.drawPolygon that takes an array of Points as it's args.
Did something similar, where I drew a polygon of three sides. Might help..
for (int i = 0; i < 3; i++){
polygon1.addPoint(
(int) (40 + 50 * Math.cos(i * 2 * Math.PI / 3)),
(int) (150 + 50 * Math.sin(i * 2 * Math.PI / 3))
);
}
g.drawPolygon(polygon1);