Though the GeometricObject is without errors, the GeoCircle shows an error saying GeoCircle is not abstract and does not override the abstract method compareTo(GeometricObject) though the compareTo method is not written as an abstract class
//abstract class GeometricObject that implements the comparable interface
public abstract class GeometricObject implements Comparable<GeometricObject>
{
public String name;
//sample abstract class of getting area of various shapes
public abstract double getArea();
//sample abstract class for getting perimeter/circumference of various shapes
public abstract double getPerimeter();
//pass in and return name of the object selected in a system out line
public void name(String n)
{
System.out.println("This is a " + n);
}
/** A method for comparing the areas of two geometric objects and returning a boolean for their equals */
public static boolean equalArea(GeometricObject object1,GeometricObject object2)
{
//comparing double to another double
return object1.getArea()==object2.getArea();
}
// a method to find the bigger between two GeometricObjects and returning a String statement
public static void max(GeometricObject g1, GeometricObject g2)
{
if(g1.compareTo(g2)>0)
System.out.println("Object 1 is larger ");
else if (g1.compareTo(g2)<0)
System.out.println("Object 2 is larger ");
else
System.out.println("Objects are the same ");
}
// an override of the compareTo method from the implemented comparable interface
public int compareTo(GeometricObject g1, GeometricObject g2)
{
if(g1.getArea()>g2.getArea())
return 1;
else if (g1.getArea()<g2.getArea())
return -1;
else
return 0;
}
}
//a class for calculating circumference and area of a circle extended from GeometricObject
public class GeoCircle extends GeometricObject implements Comparable<GeoCircle>
{
public String name;
public double radius;
//constructor for only inputting radius of the circle
public GeoCircle(double r)
{
radius = r;
}
// 2ndconstructor taking a name for the shape and radius of the circle
public GeoCircle(String n, double r)
{
name = n;
radius = r;
}
//method to get area of the shape with previously passed in radius
public double getArea()
{
return Math.PI*Math.pow(radius,2);
}
//method to get circumference of the circle with radius previously given
public double getPerimeter()
{
return 2*Math.PI*radius;
}
//a compareTo method
public int compareTo(GeoCircle obj)
{
if (this.getArea() > obj.getArea())
return 1;
else if (this.getArea() < obj.getArea())
return -1;
else
return 0;
}
}
public int compareTo(GeometricObject g1, GeometricObject g2)
{
if(g1.getArea()>g2.getArea())
return 1;
else if (g1.getArea()<g2.getArea())
return -1;
else
return 0;
}
does not correctly override compareTo. compareTo is expected to take one argument and compare this to that argument. This could be implemented as
#Override public int compareTo(GeometricObject g) {
return Double.compare(getArea(), g.getArea());
}
For reference, adding the #Override annotation verifies that a method correctly overrides a superclass method, which would have been caught.
You should use generics in base class:
public abstract class GeometricObject<T extends GeometricObject> implements Comparable<T> {
...
// an override of the compareTo method from the implemented comparable interface
public int compareTo(T that) {
if(this.getArea()>that.getArea())
return 1;
else if (this.getArea()<that.getArea())
return -1;
else
return 0;
}
}
//a class for calculating circumference and area of a circle extended from GeometricObject
public class GeoCircle extends GeometricObject<GeoCircle> {
...
#Override // Remove this method if it doesn't differ from parent implementation
public int compareTo(GeoCircle that) {
...
}
}
Comparable interface is extremely strict. Much better solution would be implementing separate comparator and remove Comparable declaration from the base class:
class GeometricObjectAreaComparator implements Comparator<GeometricObject> {
#Override
public int compare(GeometricObject o1, GeometricObject o2) {
...
}
}
Related
I'm working on a tiny exercise java program that calculates circle and square (classes) area, that implements surface (interface) which has a method called area(). A requirement is that I have to implement a class called SumArea that has a generic method called calcArea() that receives Circle circ[] and Square square[] arrays and executes area calculation.
Program structure:
-> UseSumArea.java (main method)
-> Surface.java (interface)
-> Square.java (class that implements Surface.java)
-> Circle.java (class that implements Surface.java)
-> SumArea.java (class that executes calcArea() method)
UseSumArea.java
public class UseSumArea {
public static void main(String[] args) {
Square square[] = { new Square(2.0), new Square(5.0) };
Circle circ[] = { new Circle(3.0), new Circle(2.0) };
Surface surf[] = new Surface[square.length + circ.length];
surf[0] = square[0];
surf[1] = square[1];
surf[2] = circ[0];
surf[3] = circ[1];
SumArea sum = new SumArea();
System.out.println("Square's sum area = " + sum.calcArea(square));
System.out.println("Circle's sum area = " + sum.calcArea(circ));
System.out.println("Surface's sum area = " + sum.calcArea(surf));
}
}
Surface.java
public interface Surface {
public double area();
}
Square.java
public class Square implements Surface {
private double area;
private double side;
public Square(double l) {
this.side = l;
area();
}
#Override
public double area() {
return this.area = (this.side)*(this.side);
}
public double getArea() {
return area;
}
public void setArea(double area) {
this.area = area;
}
public double getSide() {
return side;
}
public void setSide(double side) {
this.side = side;
}
}
Circle.java
public class Circle implements Surface {
private double area;
private double radius;
public Circle (double r) {
this.radius = r;
area();
}
#Override
public double area() {
return area = (((this.radius)*(this.radius))*(Math.PI));
}
public double getRadius() {
return radius;
}
public void setRadius(double raio) {
this.raio = raio;
}
public double getArea() {
return area;
}
public void setArea(double area) {
this.area = area;
}
}
SumArea.java
public class SumArea {
private double area;
public <T> double calcArea(T[] t) { //generic method that receives Square and Circle arrays
double arrayArea = 0;
for (T a : t) {
arrayArea = arrayArea+(a.area());
}
return this.area = arrayArea;
}
}
My doubt is over this SumArea's code snippet:
arrayArea= arrayArea+(a.area());
How can I access the area() method of each Circle and Square objects inside this generic method?
You need to bound the type variable:
public <T extends Surface> double calcArea(T[] t) {
or just declare the parameter as an array of Surfaces:
public double calcArea(Surface[] t) {
Note that the latter is preferable because generics and arrays don't play very nicely together. If you were to need to have a type variable for other reasons, it would be advisable to change to a Collection, or similar:
public <T extends Surface> double calcArea(Collection<T> t) {
(And, as a minor matter of preference, I would use S rather than T to name a type variable which extends Surface)
Since the problem in regard to generic types is already addressed by Andy Turner, I just want to add a suggestion related to the class design.
I think there is a bit of redundancy in how these classes were designed. You need to create an instance of SumArea in order to do the calculation. And the result of the last of the last calcArea() method call will be stored in this object (let's assume that this calculation is far more complex and CPU-consuming).
But do we really need to store somewhere else the value is already returned by the method? In this case, the idea to cash the history of calculations (as a single variable or as a collection of values) doesn't seem to be useful because it can't be reused without knowing which objects were involved in the calculation.
And without storing the result this method will not be bound to a state, i.e. it has to be static. And since interfaces can have static methods, instead of creating a utility class for that purpose it could be placed in the Surface interface. Like that.
public interface Surface {
public double area();
public static <T extends Surface> double calcArea(T[] t) { // generic method that receives Square and Circle arrays
double arrayArea = 0;
for (T a : t) {
arrayArea += a.area();
}
return arrayArea;
}
}
Note that static behavior declared in interfaces in contrast to classes could be invoked only by using the name of an interface:
System.out.println("Circle's sum area = " + Surface.calcArea(circ));
Also note that it makes sense for both classes to have a field area inside the classes Circle and Square only if other fields will be declared as final, i.e. they must be initialed only one during the object construction and setters become unnecessary.
In this case (assuming that radius has been declared as final and is being validated when assigned so that reduce > 0) method area() will look like this:
#Override
public double area() {
if (area > 0) { // `0` is a default value for instance variables
return area; // reusing already calculated value
}
return area = radius * radius * Math.PI;
}
And there mustn't be two methods area() and getArea() leave either one or another.
I am pretty sure I can find an answer on Stackoverflow for this question. Unfortunately I do not know the specific formulation to do so.
Given following code I have the problem, that I want to avoid typechecks. The comments will probably describe it better than my words.
Right now I am trying to have a shapesystem where every shape can collide with every possible specificShape.
CollisionClass:
public class ShapeCollision {
public static boolean intersects(RectShape rectShape1, RectShape rectShape2) { return true; }
public static boolean intersects(LineShape lineShape, RectShape rectShape) { return true; }
public static boolean intersects(RectShape rectShape1, Shape shape) { return true; }
public static boolean intersects(LineShape lineShape, Shape shape) { return true; }
public static boolean intersects(Shape shape1, Shape shape2){ return true; }
}
ShapeClasses:
public class RectShape extends Shape {
Vector size;
public RectShape(Vector pos, Vector size) {
super(pos);
this.size = size;
}
#Override
public boolean intersects(IShape shape) {
return ShapeCollision.intersects(this, shape);
}
}
public class LineShape extends Shape {
Vector pos2;
public LineShape(Vector pos, Vector pos2) {
super(pos);
this.pos2 = pos2;
}
#Override
public boolean intersects(IShape shape) {
return ShapeCollision.intersects(this, shape);
}
}
public class Shape implements IShape {
protected Vector pos;
public Shape(Vector pos) {
this.pos = pos;
}
#Override
public Vector getPos() {
return pos;
}
#Override
public void setPos(Vector pos) {
this.pos = pos;
}
#Override
public void move(Vector movementAmount) {
pos.add(movementAmount);
}
#Override
public boolean intersects(IShape shape) {
return ShapeCollision.intersects(this, shape);
}
}
Here is the confusing part for me:
Shape rect = new RectShape(new Vector(0,0), new Vector(20,20));
Shape rect2 = new RectShape(new Vector(0,0), new Vector(20,20));
Shape line = new LineShape(new Vector(0,0), new Vector(20,20));
//Since I am saving shape and no specific shapetype, it will pass shape and pick the specific superFunction
//Right now it calls the intersects(RectShape rectShape1, Shape shape) function due to calling it through the shape variable
rect.intersects(rect2);
//This calls the intersects(LineShape lineShape, Shape shape) function
rect.intersects(line);
//This calls the intersects(Shape shape1, Shape shape2) function
ShapeCollision.intersects(rect, line);
How can I achieve it without specifying the type of the variable, that the 'correct' function with the subclass parameter is called. (e.g.: (LineShape lineShape, RectShape rectShape))
I do not want to make any typechecks in those functions and call the functions specifically, but to use some DesignPatters or something similar if possible :)
What you want is NOT achievable without some type checking inside the functions or some explicit casting done on the Shape instances before passing them to the function calls.
Of course you could declare the objects references with the specific classes, but i guess that is not really helpful.
How should I pass the "type" parameter of a constructor in an if/else statement? For eg - cal(2,2,0,rectangle). So if the type=rectangle then calculate area of a rectangle. If type=circle, calculate the area of a circle.
I am using a single constructor. My issue is that I know the logic but I can't write it in syntax. I am using Java or Apex.
I want to use if-else statement. How should I pass the type parameter in the code?
My program is like this -
if "type"=square, the compiler will call calculate area of the square.
if "type"=circle, the compiler will call calculate area of the circle.
public class Area {
private String type;
private Integer length;
private Integer breadth;
private Integer height;
private Integer area;
public void setType(String t){
type=t;
}
public void setLength(Integer l){
length=l;
}
public void setbreadth(Integer b){
breadth=b;
}
public void setheight(Integer h){
height=h;
}
/* public void setArea(Integer a){
area=a;
} */
public Integer getLength(){
return length;
}
public Integer getbreadth(){
return breadth;
}
public Integer getheight(){
return height;
}
public string gettype(){
return type;
}
public Integer AreaRectangle(){
return area=length*breadth;
}
public Integer AreaSquare(){
return area=length*length;
}
public integer AreaTriangle(){
return area=1/2 *(breadth*height);
}
public Area(){ // default constructor
length=9;
breadth=2;
height=7;
}
public Area(String t,Integer l ,Integer b,Integer h ){ // parameterised constructor
type=t;
length=l;
breadth=b;
height=h;
}
}
You don't. You create an abstract class called shape.
public abstract class Shape {
abstract double area();
}
And then two other classes that extend Shape and each provides the proper implementation
public class Square extends Shape {
private int side;
public Square(int side) {
this.side = side;
}
public double area() {
return (double) side * side;
}
}
Now at the place you want to call it:
Shape shape = new Square(5);
double area = shape.area();
Int radius = 4;
shape = new Circle(radius);
double circle area = shape.area();
I have two objects - RightTriangle and Rectangle. Both classes implement "Shape" interface which has 2 abstract methods for area and perimeter. In RightTriangle class I implement comparable and my compareTo returns area:perimeter ratio. I do the same thing in Rectangle class. In the demo I want to sort an array of RightTriangle objects and Rectangle Object using Collections.sort().
Shape Interface Code:
public interface Shape
{
public double getArea();
public double getPerimeter();
}
RightTriangle Code:
public class RightTriangle implements Shape, Comparable<Shape>
{
private int leg1, leg2;
public RightTriangle(int lg1, int lg2)
{
leg1 = lg1;
leg2 = lg2;
}
public double getArea()
{
return (.5*leg1*leg2);
}
public double getPerimeter()
{
return (leg1+leg2 + getHypotenuse());
}
private double getHypotenuse()
{
return (Math.sqrt(Math.pow(leg1,2)+Math.pow(leg2,2)));
}
public int compareTo(Shape obj)
{
return (int)(getArea()/getPerimeter());
}
}
Rectangle Code:
public class Rectangle implements Shape, Comparable<Shape>
{
private int length, width;
public Rectangle(int l, int w)
{
length = l;
width = w;
}
public double getArea()
{
return (width*length);
}
public double getPerimeter()
{
return (2*width + 2*length);
}
public int compareTo(Shape obj)
{
return (int)(getArea()/getPerimeter());
}
}
Demo:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Collections;
public class Demo
{
public static void main (String[] args)
{
RightTriangle right = new RightTriangle(12,14);
Rectangle rect = new Rectangle(7,10);
ArrayList<Shape> al = new ArrayList<Shape>();
al.add(right);
al.add(rect);
Collections.sort(al);
for (int i = 0; i < al.size(); i++)
{
System.out.println (al.get(i));
}
}
}
I am getting an error - "error: no suitable method found for sort(ArrayList). How do I fix this?
Thanks.
1. You need to extend Comparable interface to Shape interface and not traingle and rectangle class as below
public interface Shape extends Comparable<Shape>
{
public double getArea();
public double getPerimeter();
public int compareTo(Shape obj);
}
2. RightTriangle and Rectangle class will only implement Shape interface as
public class RightTriangle implements Shape
public class Rectangle implements Shape
**3. Implement toString method in both RightTriangle and Rectangle class by right click on code ..select source-> generate toString()
#Override
public String toString() {
return "RightTriangle [leg1=" + leg1 + ", leg2=" + leg2 + "]";
}
#Override
public String toString() {
return "Rectangle [length=" + length + ", width=" + width + "]";
}
** See the result i got after correcting your code
Create a Java class named “Circle” that implements java.io.Serializable interface and models a circle based on radius. Radius cannot be less than zero. Implement the getter and setter method for radius. Also include an overriding of toString in the circle class. Create the class' comparator which compares two objects of type Circle.
This is what I have so far
import java.io.Serializable;
public class Circle implements Serializable, Comparable<Circle> {
private int radius = 1;
public Circle() {
}
public Circle(int radius) {
setRadius(radius);
}
public void setRadius(int v) {
if (v > 0) {
this.radius = v;
}
}
public int getRadius() {
return this.radius;
}
#Override
public String toString() {
return "Circle{" + "radius=" + radius + '}';
}
#Override
public int compareTo(Circle o) {
//no idea what to put here
}
}
This my comparator class
import java.util.Comparator;
public class CompareCircle implements Comparator<Circle> {
CompareCircle(Circle c1, Circle c2) {
}
#Override
public int compare(Circle o1, Circle o2) {
if (o1.getRadius() > o2.getRadius()) {
return o1.getRadius();
} else {
return o2.getRadius();
}
}
}
My question is did I do this right or no?
First, you don't need to implement Comparable or override compareTo().
According to the documentation, this is what compare() should return:
Returns a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second.
You can use Integer.compare() to satisfy these requirements:
Returns:
the value 0 if x == y; a value less than 0 if x < y; and a value greater than 0 if x > y
import java.util.Comparator;
public class CompareCircle implements Comparator<Circle> {
#Override
public int compare(Circle o1, Circle o2) {
return Integer.compare(o1.getRadius(), o2.getRadius());
}
}
To compare, you need to create an instance of CompareCircle. You can use it with Collections.max() to retrieve the largest object:
import java.util.ArrayList;
import java.util.Collections;
public class Main {
public static void main(String[] args){
ArrayList<Circle> list = new ArrayList<Circle>() {{
add(new Circle(4));
add(new Circle(7));
add(new Circle(2));
}};
CompareCircle comp = new CompareCircle();
Circle c = Collections.max(list, comp);
System.out.println(c.getRadius());
}
}
Ouput:
7
As JB pointed out Circle class does not need to implement Comparable if you use comperator:
public class Circle implements Serializable /*, Comparable<Circle> */{
In CompareCircle you can drop the constructor (actually use the default constructor CompareCircle() ).
The compare method should also handle the case of two equal circles:
#Override
public int compare(Circle o1, Circle o2) {
//you may want to consider cases where one circle or both are null
if (o1.getRadius() > o2.getRadius()) {
return o1.getRadius();
} else if (o1.getRadius() == o2.getRadius()) {
return 0;
}
return o2.getRadius();
}
}