Implementing generic method from interface in java - java

I have two interfaces and one class implementing them. In the interface I have shown one usual method and one generic method. When implementing them in main method usual method shows correct result, but the generic one does not. If possible could you tell me, why the increase_twice() method does not return correct result, please? Here are my code:
Rectangle.java:
public class Rectangle implements TwoDShape {
private double width, height;
public Rectangle (double width, double height) {
this.width = width;
this.height = height;
}
public double area() {
return width * height;
}
public double perimeter() {
return 2.0 * (width + height);
}
public void describe() {
System.out.println("Rectangle[width=" + width + ", height=" + height + "]");
}
#Override
public Rectangle increase_twice() {
// TODO Auto-generated method stub
return new Rectangle(2*this.width, 2*this.height);
}
}
TwoDShape.java:
public interface TwoDShape extends GeometricShape {
public double area();
}
GeometricShape.java:
public interface GeometricShape<T extends GeometricShape<T>>
{
public void describe();
public T increase_twice();
}
And finally test class ArrayListExample.java
import java.util.ArrayList;
public class ArrayListExample {
public static void describe_all( ArrayList<? extends GeometricShape> shapes )
{
for(int i=0;i<shapes.size();i++)
{
shapes.get(i).describe();
}
System.out.println("Total number of shapes:"+ shapes.size());
}
private static ArrayList<Rectangle> increase_size(ArrayList<Rectangle> rects)
{
for(int i=0;i<rects.size();i++)
{
rects.get(i).increase_twice();
}
return rects;
}
public static void main(String[] args) {
System.out.println("The result of describe() method:");
System.out.println();
System.out.println("Example rectangles");
ArrayList<Rectangle> rects = new ArrayList<Rectangle>();
rects.add(new Rectangle(2.0, 3.0));
rects.add(new Rectangle(5.0, 5.0));
describe_all(rects);
System.out.println();
System.out.println("The result of increase_twice() method:");
System.out.println();
System.out.println("Example rectangles after increase:");
ArrayList<Rectangle> double_rects = increase_size(rects);
describe_all(double_rects);
}
}
I expect that the increase_twice will return rectangles with Rectangle[width=4.0, height=6.0]
Rectangle[width=10.0, height=10.0] but it instead return the same as describe method which is:
Rectangle[width=2.0, height=3.0]
Rectangle[width=5.0, height=5.0]
If possible could you tell me where I make a mistake please?

I think the issue is in increase_twice function. When you are calling rects.get(i).increase_twice(); you are actually creating a new Rectangle object with doubled values and returning. You are not updating the current object.
The increase_twice method should be:
#Override
public void increase_twice() {
// TODO Auto-generated method stub
this.width *= 2;
this.height *= 2;
}
This way you will update the width and height values of the current object that you are getting from the ArrayList.
You might have to change the definition of increase_twice() because i don't think you need to return a new Rectangle object.
Let me know if that works.

Rectangle.increase_twice() returns a new Object. However, in ArrayListExample.increase_size(), the returned object isn't set.
You may modify that method to this:
private static ArrayList<Rectangle> increase_size(ArrayList<Rectangle> rects) {
for (int i = 0; i < rects.size(); i++) {
rects.set(i, rects.get(i).increase_twice());
}
return rects;
}
Or you may modify Rectangle.increase_twice() to this:
#Override
public void increase_twice() {
// TODO Auto-generated method stub
this.width = 2 * this.width;
this.height = 2 * this.height;
}
And GeometricShape.increase_twice() declaration to this:
public void increase_twice();

Related

Java Create class instance based on user input

I have some class Shape.
public abstract class Shape {
String shapeColor;
public Shape(String shapeColor){
this.shapeColor = shapeColor;
}
abstract public double calcArea();
#Override
public String toString() { return "Shape"; }
public String getShapeColor() { return shapeColor; }
}
Also, I have classes that extend from Shape: Triangle, Rectangle and Circle.
public class Triangle extends Shape {
double a, h;
public Triangle(String shapeColor, double a, double h) {
super(shapeColor);
this.a = a;
this.h = h;
}
#Override
public double calcArea() {return a * h / 2;}
#Override
public String toString() {
return "Triangle";
}
}
public class Rectangle extends Shape {
double a, b;
public Rectangle(String shapeColor, double a, double b) {
super(shapeColor);
this.a = a;
this.b = b;
}
#Override
public double calcArea() {
return a * b;
}
#Override
public String toString() {
return "Rectangle";
}
}
public class Circle extends Shape {
double r;
public Circle(String shapeColor, double r) {
super(shapeColor);
this.r = r;
}
#Override
public double calcArea() {
return (Math.PI * r * r);
}
#Override
public String toString() {
return "Circle";
}
}
I want to create Arraylist<Shape> shapes and add shapes to it based on user input.
So, I want to have something like
String[] userInput = scanner.nextLine().split(", ");
Shape shape = createNewShape(userinput)
For example:
"Circle, Blue, 7" -> Shape shape = new Circle("Blue", 7)
"Rectangle, Red, 5, 10" -> Shape shape = new Rectangle("Red", 5, 10)
But I want this to work even if new class that extends from Shape is created.
For example if I will have new Shape Cube I will not have need to add something to my code:
"Cube, Red, 9" -> Shape shape = new Cube("Red", 9)
This question is close to what I need, but my classes have different amount of parameters. Maybe someone can give me a piece of advice how to make it work for different amount of parameters.
You can search for Constructors on a specific package.
For example, put all your shapes together in a x-named package and call Class.forName to get them.
public static void main(String[] args) {
List<Shape> shapes = new ArrayList<>();
shapes.add(create("Triangle", "Orange", 5, 6));
shapes.add(create("Circle", "Blue", 7));
shapes.add(create("Rectangle", "Red", 5, 10));
shapes.forEach(System.out::println);
}
private static Shape create(String constructor, Object... objects) {
try {
final Constructor<?> _constructor = Class.forName("com.shapes." + constructor).getConstructors()[0];
return (Shape) _constructor.newInstance(objects);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
My structure:
+com.mainPackage
main.java
+com.shapes
Shape.java
Triangle.java
Rectangle.java
Circle.java

Having trouble with "Rectangles"

Create a class Rectangle with instance variables length and width to
have default value of 1 for both of them. The class should have
suitable set and get methods for accessing its instance variables. The
set methods should verify that length and width are assigned a
value that is larger than 0.0 and is lesser than 20.0, Provide
suitable public methods to calculate the rectangle’s perimeter and
area. Write a suitable class "RectangleTest" to test the Rectangle
class.
What I came up with:
package rectangle;
public class Rectangle
{
private double width;
private double length;
public Rectangle()
{
width=1;
length=1;
}
public Rectangle(double width, double length)
{
this.width = width;
this.length = length;
}
public void setWidth(float width)
{
this.width = width;
}
public float getWidth()
{
return (float) width;
}
public void setLength(float length)
{
this.length = length;
}
public float getLength()
{
return (float) length;
}
public double getPerimeter()
{
return 2 * (width + length);
}
public double getArea()
{
return width * length;
}
}
package rectangle;
import java.util.Scanner;
public class RectangleTest extends Rectangle
{
public static void main(String[] args)
{
Scanner RectangleTest = new Scanner(System.in);
System.out.print("Length: ");
float lengthInput = RectangleTest.nextFloat();
System.out.print("Width: ");
float widthInput = RectangleTest.nextFloat();
Rectangle rectangle = new Rectangle (lengthInput, widthInput);
System.out.printf("Perimeter: %f%n",
rectangle.getPerimeter());
System.out.printf("Area: %f%n",
rectangle.getArea());
}
}
Code is fine, it's just I am not sure how to implement the between 0 - 20 without breaking everything and have tried different things.
I'd check it and throw an IllegalArgumentException if the value isn't valid, e.g.:
public void setLength(float length) {
if (length <= 0f || length >= 20.0f) {
throw new IllegalArgumentException("Invalid length " + length);
}
this.length = length;
}

How to implement one generic method for two classes in java

I have an interface that has one ordinary method and one generic method. I have implemented ordinary method for two different classes, but do not now how to do that with generic method. Here is my code:
Sphere.java:
public class Sphere implements GeometricShape<Sphere> {
private double radius;
public Sphere (double radius) {
this.radius = radius;
}
public double volume() {
return (4.0 / 3.0) * Math.PI * radius * radius * radius;
}
public void describe() {
System.out.println("Sphere[radius=" + radius + "]");
}
#Override
public Sphere supersize()
{
this.radius*=2;
return new Sphere(radius);
}
}
Rectangle.java
public class Rectangle implements TwoDShape {
private double width, height;
public Rectangle (double width, double height) {
this.width = width;
this.height = height;
}
public double area()
{
return width * height;
}
public double perimeter()
{
return 2.0 * (width + height);
}
public void describe()
{
System.out.println("Rectangle[width=" + width + ", height=" + height + "]");
}
#Override
public Rectangle supersize()
{
this.width*=2;
this.height*=2;
return new Rectangle(width, height);
}
}
TwoDShape.java:
public interface TwoDShape extends GeometricShape
{
public double area();
}
ThreeDShape.java:
public interface ThreeDShape extends GeometricShape<ThreeDShape>
{
public double volume();
}
GeometricShape.java:
public interface GeometricShape<T extends GeometricShape<T>>
{
public void describe();
public T supersize();
}
and finally main class ArrayListExample.java:
import java.util.ArrayList;
public class ArrayListExample {
public static void describe_all( ArrayList<? extends GeometricShape> shapes )
{
for(int i=0;i<shapes.size();i++)
{
shapes.get(i).describe();
}
System.out.println("Total number of shapes:"+ shapes.size());
}
public static void main(String[] args) {
System.out.println("The describe() method:");
System.out.println();
System.out.println("Example rectangles");
ArrayList<Rectangle> rects = new ArrayList<Rectangle>();
rects.add(new Rectangle(2.0, 3.0));
rects.add(new Rectangle(5.0, 5.0));
describe_all(rects);
System.out.println();
ArrayList<Sphere> spheres = new ArrayList<Sphere>();
spheres.add(new Sphere(10.0));
spheres.add(new Sphere(50.0));
spheres.add(new Sphere(0.0));
System.out.println("Example spheres");
describe_all(spheres);
System.out.println();
System.out.println("The supersize() method:");
System.out.println();
ArrayList<Rectangle> double_rects = supersize_list(rects);
describe_all(double_rects);
System.out.println();
ArrayList<Sphere> double_spheres = supersize_list(spheres);
describe_all(double_spheres);
}
}
How can I implement supersize_list method that it takes supersize method from both rectangle and sphere and outputs like
Rectangle[width=4.0, height=6.0]
Rectangle[width=10.0, height=10.0]
Total number of shapes: 2
Sphere[radius=20.0]
Sphere[radius=100.0]
Sphere[radius=0.0]
Total number of shapes: 3
Could you help me with this, please? I greatly appreciate your help!
The class hierarchy looks inconsistent. For example, you have ThreeDShape extends GeometricShape<ThreeDShape> and TwoDShape extends GeometricShape at the same time, for no obvious reason. It's not fun to write a generic method for these types.
Here's a less-confusing version. (I hope) Note: I choose not to change the size of the shape itself in supersize method, instead let it return a bigger shape while keeping the original unchanged.
1. GeometricShape
/**
* A geometric shape interface. You can do two things with it.
* 1. Ask it to describe itself (to stdout);
* 2. Ask it to return a bigger version of itself (double the size).
*/
public interface GeometricShape<T extends GeometricShape<T>> {
/**
* Print a description to STDOUT
*/
void describe();
/**
* Returns a bigger shape.
* #return Something that's a GeometricShape
*/
T supersize();
}
2. Shape2D and Rectangle
/**
* A 2-dimensional shape.
* It has area.
* Its supersize() method should return a Shape2D instance.
*/
public interface Shape2D<T extends Shape2D<T>> extends GeometricShape<T> {
double area();
}
/**
* A rectangle.
*/
public final class Rectangle implements Shape2D<Rectangle> {
private final double width;
private final double height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
#Override
public String toString() {
return "Rectangle{" +
"width=" + width +
", height=" + height +
'}';
}
#Override
public void describe() {
System.out.println(this);
}
#Override
public Rectangle supersize() {
return new Rectangle(width*2, height*2);
}
#Override
public double area() {
return width * height;
}
}
3. Shape3D and Sphere
/**
* A 3-dimensional shape.
* It has volume.
* Its supersize() method should return a Shape3D instance.
*/
public interface Shape3D<T extends Shape3D<T>> extends GeometricShape<T> {
double volume();
}
/**
* A sphere
*/
public final class Sphere implements Shape3D<Sphere> {
private final double radius;
public Sphere(double radius) {
this.radius = radius;
}
#Override
public String toString() {
return "Sphere{" +
"radius=" + radius +
'}';
}
#Override
public void describe() {
System.out.println(this);
}
#Override
public Sphere supersize() {
return new Sphere(radius*2);
}
#Override
public double volume() {
return 4*Math.PI*Math.pow(radius, 3)/3;
}
}
Now the generic method that transforms a list
public static <T extends GeometricShape<T>>
List<T> supersize_list(List<T> list) {
List<T> result = new ArrayList<>();
for (T shape : list) {
result.add(shape.supersize());
}
return result;
}
You do not need to return a new Object. For Rectangle for example
#Override
public void supersize()
{
this.width*=2;
this.height*=2;
}
is sufficient

Java - How to print methods of a certain object from ArrayList?

Basically I have an ArrayList of Objects. There are different types of objects, such as Triangles, Rectangles, and Spheres. Each object has its own method, such as getArea, getPerimeter, and getVolume. These methods are different for each object. How do I iterate through the ArrayList to print out all of the methods of each object?
So say I start with a Triangle. How do I print its getArea and getPerimeter methods with a for loop and a switch block / if statement?
You can use a simple for loop to iterate over your ArrayList, and then call the toString() method of the object:
for (int = 0; i < arrayList.size(); i++)
{
System.out.println(arrayList.get(i).toString());
}
To override the toString method of your class, just add the method, pretty simple:
class Rectangle
{
//Member variables
int width, height; //Example
//Member functions
getArea { ... }
//toString
public String toString()
{
return String.valueOf(getArea());
}
}
for(int i=0; i<listOfObjects.length; i++) {
Object obj = listOfObjects[i];
if (obj instanceof Triangle) {
Triangle t = (Triangle) obj;
t.getArea();
} else if (obj instanceof Rectangle) {
Rectangle r = (Rectangle) obj;
r.getPerimeter();
} else {
Sphere s = (Sphere) obj;
s.getSomeOtherThing();
}
}
Check this. An alternative to instanceof operator
ArrayList arr=new ArrayList();
arr.add(new Traingle());
arr.add(new Rectangle());
arr.add(new Sphere());
for(Object obj:arr){
int value=0;
switch (obj.getClass().getSimpleName()){
case "Rectangle":
value=((Rectangle) obj).getPerimeter();
break;
case "Traingle":
value=((Traingle) obj).getArea();
break;
case "Sphere":
value=((Sphere) obj).getVolume();
break;
default:
break;
}
System.out.println("Object "+obj.getClass().getSimpleName()+":"+value);
}
Why not use an Interface?
package com.spiderman;
public interface Shape {
public void getArea();
public void getPerimeter();
public void getVolume();
}
package com.spiderman;
public class Rectangle implements Shape {
#Override
public void getArea() {
System.out.println("area of Rectangle");
}
#Override
public void getPerimeter() {
System.out.println("perimiter of Rectangle");
}
#Override
public void getVolume() {
System.out.println("volume of Rectangle");
}
}
package com.spiderman;
public class Triangle implements Shape {
#Override
public void getArea() {
System.out.println("area of Triangle");
}
#Override
public void getPerimeter() {
System.out.println("perimiter of Triangle");
}
#Override
public void getVolume() {
System.out.println("volume of Triangle");
}
}
package com.prash;
public class Sphere implements Shape {
#Override
public void getArea() {
System.out.println("area of Sphere");
}
#Override
public void getPerimeter() {
System.out.println("perimiter of Sphere");
}
#Override
public void getVolume() {
System.out.println("volume of Sphere");
}
}
package com.spiderman;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Shape> list = new ArrayList<Shape>();
list.add(new Rectangle());
list.add(new Triangle());
list.add(new Sphere());
for (int i = 0; i < list.size(); i++) {
Shape shape = list.get(i);
shape.getArea();
shape.getPerimeter();
shape.getVolume();
System.out.println("------------------");
}
}
}
OUTPUT:
area of Rectangle
perimiter of Rectangle
volume of Rectangle
area of Triangle
perimiter of Triangle
volume of Triangle
area of Sphere
perimiter of Sphere
volume of Sphere

How to create an object from data in a file and assign it to an array?

I need to take information from a file and create them into objects and put them into an array so I can compare the areas of the objects and list in the array which object has the largest area and its location in the array.
I'm confused on how I take the information from the file and create each one into a object (circle or rectangle) and then assign that object into an array after it has been created. I think my other classes are fine, I'm just stuck on finishing the driver.
Normally, I would do something like Circle c1 = new Circle(); to create a new object, but how do I do that from a file with predefined information and assign it to an array?
Data:
“CIRCLE”, 1, “blue”, true
“RECTANGLE”, 1, 2, “blue”, true
“RECTANGLE”, 10, 2, “red”, true
“CIRCLE”, 2, “green”
“RECTANGLE”
“CIRCLE”
Driver:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;
public class Driver {
public static void main(String[] args) throws FileNotFoundException {
Scanner input = new Scanner(new File("C:/Users/Charles/Desktop/GeometricObjectsData.txt"));
ArrayList<GeometricObject> list = new ArrayList<GeometricObject>();
while (input.hasNext()) {
String line = input.nextLine();
System.out.println(line);
}
}
}
GeometricObject:
public abstract class GeometricObject {
//class variables
private String color;
private boolean filled;
//constructors
public GeometricObject() {
super();
color = "white";
filled = false;
}
public GeometricObject(String color, boolean filled) {
super();
this.color = color;
this.filled = filled;
}
//mutators
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public boolean isFilled() {
return filled;
}
public void setFilled(boolean filled) {
this.filled = filled;
}
//user-defined methods
public abstract double getArea();
public abstract double getPerimeter();
#Override
public String toString() {
return super.toString() + " \tColor=" + this.getColor() + " \tFilled=" + this.isFilled();
}
}
Circle:
public class Circle extends GeometricObject {
//class variables
private double radius;
//constructors
public Circle() {
super();
radius = 1;
}
public Circle(double radius, String color, boolean filled) {
super(color, filled);
this.radius = radius;
}
//mutators
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
//user-defined methods
#Override
public double getArea() {
//area of a circle
return (radius * radius * Math.PI);
}
#Override
public double getPerimeter() {
//perimeter of a circle
return (2 * radius * Math.PI);
}
#Override
public String toString() {
return super.toString() + "\nCircle: Radius=" + this.getRadius();
}
}
Rectangle:
public class Rectangle extends GeometricObject {
//class variables
private double height;
private double width;
//constructors
public Rectangle() {
super();
height = 1;
width = 1;
}
public Rectangle(double height, double width, String color, boolean filled) {
super(color,filled);
this.height = height;
this.width = width;
}
//mutators
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public double getWidth() {
return width;
}
public void setWidth(double width) {
this.width = width;
}
//user-defined methods
#Override
public String toString() {
return super.toString() + "\nRectangle: Height=" + this.height + "\tWidth=" + this.width;
}
#Override
public double getArea() {
return (height * width);
}
#Override
public double getPerimeter() {
return (2 * height + 2 * width);
}
}
In your text file, you have special quotes around your shape items. This will make your life more difficult, so you should change that, if possible
Example of how to make objects (from your main method):
while (input.hasNext()) {
String line = input.nextLine();
System.out.println(line);
String[] parts = line.split(",");
if (parts[0].indexOf("Circle") != -1) {
Circle c = new Circle();
// ... parse the rest of the attributes to set up your circle
} else if ... // fill in the other shape cases
}

Categories

Resources