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
Related
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 was told that i should make a JUnit Test to check if all the codes are working. I dont know anything about JUnit that Is why im asking you guys. Anyway, here is my code:
package cst8284.shape;
public abstract class BasicShape {
private double width;
public double getWidth(){return width;}
public void setWidth(double width){this.width = width;}
#Override
public String toString(){
return ("BasicShape Overrides " + super.toString());
}
public abstract double getArea();
public abstract double getPerimeter();
}
Here is where i should make testing,
package cst8284.shape;
public class TestBasicShape {
public static void main(String[] args){
Circle circle = new Circle(2.0);
System.out.println(circle.toString());
System.out.println("The perimeter of the circle is " + circle.getPerimeter());
System.out.println("The area of the circle is: " + circle.getArea() + "\n");
Square square = new Square(2.0);
System.out.println(square.toString());
System.out.println("The perimeter of the square is " + square.getPerimeter());
System.out.println("The area of the square is: " + square.getArea() + "\n");
Rectangle rect1 = new Rectangle(2.0,3);
System.out.println(rect1.toString());
System.out.println("The perimeter of the rectangle is " + rect1.getPerimeter());
System.out.println("The area of the rectangle is: " + rect1.getArea() +"\n");
Rectangle rect2 = new Rectangle(rect1);
Rectangle rect3 = new Rectangle(2.0, 1.0);
System.out.println("The square and the circle are " + (square.equals(circle)?"":"not ") + "equal");
System.out.println("The rectangle and the square are " + (rect1.equals(square)?"":"not ") + "equal");
System.out.println("Rectangles 1 and 2 are " + (rect2.equals(rect1)?"":"not ") + "equal");
System.out.println("Rectangles 2 and 3 are " + (rect2.equals(rect3)?"":"not ") + "equal");
}
}
package cst8284.shape;
public class Circle extends BasicShape {
public Circle(){
}
public Circle(double width){
setWidth(width);
}
public Circle(Circle circle) {
setWidth(circle.getWidth());
}
//Getters
public double getArea() {
return Math.PI * (getWidth()/2) * (getWidth()/2);
}
public double getPerimeter() {
return 2*Math.PI*getWidth()/2;
}
#Override
public String toString(){
return ("Circle Overrides " + super.toString());
}
#Override
public boolean equals(Object obj){
if (!(obj instanceof Circle)) {
return false;
}
Circle c = (Circle)obj;
return (this.getWidth() == c.getWidth());
}
}
package cst8284.shape;
public class Square extends BasicShape{
public Square() {
}
public Square(double width) {
setWidth(width);
}
public Square(Square square) {
setWidth(square.getWidth());
}
//Getters
public double getArea() {
return getWidth()*2;
}
public double getPerimeter() {
return 4*getWidth();
}
#Override
public String toString(){
return ("Square Overrides " + super.toString());
}
#Override
public boolean equals(Object obj){
if (!(obj instanceof Square)) {
return false;
}
Square s = (Square)obj;
return (this.getWidth() == s.getWidth());
}
}
package cst8284.shape;
public class Rectangle extends Square{
private double height;
public Rectangle() {
}
public Rectangle(double width, double height) {
setWidth(width);
setHeight(height);
}
public Rectangle(Rectangle rectangle) {
setWidth(rectangle.getWidth());
setHeight(rectangle.getHeight());
}
public double getHeight(){
return height;
}
public void setHeight(double height){
this.height=height;
}
public double getArea() {
return getWidth()*getHeight();
}
public double getPerimeter() {
return 2*(getHeight()+getWidth());
}
#Override
public String toString(){
return ("Rectangle Overrides " + super.toString());
}
#Override
public boolean equals(Object obj){
if (!(obj instanceof Rectangle)) {
return false;
}
Rectangle r = (Rectangle)obj;
return (this.getWidth() == r.getWidth() && this.getHeight() == r.getHeight());
}
}
In this program, i am trying to calculate the area and perimeter of Circle and Square(subclasses of BasicShape) and Rectangle(subclass of Square) and also trying to compare whether each shape are equal(in shape or in size)
Thank you in advance!
I have found the easiest way to approach testing is to make a test class for each of the classes whose behaviour you would like to test in your system, and place these test classes in a separate package.
Then, say you want to test the methods in the rectangle class.
//imports
public void testRectangle(){
Rectangle rectange;
#Before
public void setup(){
rectangle = new Rectangle();
}
//Say you want to test whether the setHeight method works as it should
#Test
public void testSetHeight(){
rectangle.setHeight(10.0);
assertEquals(10.0, rectangle.getHeight());
}
//The rest of the methods you would like to test
A few things to note :
Methods in the test class never takes in any parameters.
#Before means the method is going to run before each of the test methods. This allows you to setup anything you will need for the tests to run. You must have #Test before each test method. The example I have provided above is very simple and by no means exhaustive, so you should look up the JUnit documentation and learn more.
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();
}
}
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) {
...
}
}
I have a problem with my program and I can't find the reason why thought. It points at the public static void main(String[] args) line nowhere else, can't figure it out :(
Tried checking for the braces, if by accident I missed one or two but still no, it is not an interface implementation so I don't have to set each method of the abstract class to public in the implementation...
abstract class Shape {
private String name;
Shape(String name0) {name = name0;}
abstract double area();
abstract double perim();
void put() {
System.out.println(name + " with area " + area()+ " and perimeter " + perim());
}
}
class Circle extends Shape{
private double r;
Circle(String name0, double inR) {
super(name0);
r = inR;
}
double area() {
return (Math.sqrt(r)*Math.PI);
}
double perim() {
return 2*(Math.PI * r);
}
}
class Rectangle extends Shape{
private double a,b;
Rectangle(String name0, double a0, double b0) {
super(name0);
a=a0; b=b0;
}
double area() {
return (a*b);
}
double perim() {
return 2*(a+b);
}
}
}
class TestClass {
public static void main(String args[]) {
Shape[] figures = {new Rectangle("Rectangle", 2.0, 3.0), new Rectangle("Square", 4.0, 4.0), new Circle("Circle", 2.0)};
for (Shape s: figures)
s.put();
}
}
You have an extra closing brace } before the main method. Just remove that.
Suggestion: It is really wise to use an IDE to do coding because you can get away from these compilation errors easily and quickly.