How to implement one generic method for two classes in java - 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

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

Implementing generic method from interface in 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();

Error cannot find symbol- Java class and methods

What's up guys,
I keep receiving this error, cannot find symbol Circle aCircle = new Circle(); , when trying to compile the driver code my professor gave us. I'm wondering if it is because I haven't added it to my circle.java method. This is the circle driver.
package lab7;
public class CircleDriver {
public static void main(String[] args) {
Circle aCircle = new Circle();
aCircle.setColor("green");
aCircle.setRadius(10);
aCircle.display();
Double circleArea = aCircle.computeArea();
Double circumference = aCircle.computeCircumference();
System.out.println("circle area: " + circleArea);
System.out.println("circle circumference: " + circumference);
System.out.println();
}
}
This is my circle method.`
public class Circle {
private String color;
private int radius;
public Circle(String color, int radius) {
this.color = color;
this.radius = radius;
}
public Circle() {
Circle aCircle = new Circle();
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getRadius() {
return radius;
}
public void setRadius(int radius) {
this.radius = radius;
}
public void display() {
System.out.println("I am a circle");
System.out.println("My color is " + color);
System.out.println("My radius is " + radius);
}
public double computeArea() {
return (Math.PI * Math.pow(radius, 2));
}
public double computeCircumference() {
return (2 * Math.PI * radius);
}
}
You need to call a super() constructor when calling a circle. When you call
Circle aCircle = new Circle();
You are trying to initialize a circle in the local aspect. I think you are trying to inherit the Circle class that is already in java.
Leaving the circle constructor as
public Circle() {}
Should theoretically work to instantiate your class.
Use this code. You have mistake in constructor. I hope it will solve your issue.
In Circle.java, instead of
public Circle() {
Circle aCircle = new Circle();
}
Use this code
public Circle() {
super();
// TODO Auto-generated constructor stub
}
CircleDriver.java
public class CircleDriver {
public static void main(String[] args) {
Circle aCircle = new Circle();
aCircle.setColor("green");
aCircle.setRadius(10);
aCircle.display();
Double circleArea = aCircle.computeArea();
Double circumference = aCircle.computeCircumference();
System.out.println("circle area: " + circleArea);
System.out.println("circle circumference: " + circumference);
System.out.println();
}
}
Circle.java
public class Circle {
private String color;
private int radius;
public Circle() {
super();
// TODO Auto-generated constructor stub
}
public Circle(String color, int radius) {
super();
this.color = color;
this.radius = radius;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getRadius() {
return radius;
}
public void setRadius(int radius) {
this.radius = radius;
}
public void display() {
System.out.println("I am a circle");
System.out.println("My color is " + color);
System.out.println("My radius is " + radius);
}
public double computeArea() {
return (Math.PI * Math.pow(radius, 2));
}
public double computeCircumference() {
return (2 * Math.PI * radius);
}
}
Output:
I am a circle
My color is green
My radius is 10
circle area: 314.1592653589793
circle circumference: 62.83185307179586

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
}

Java-using a class and reading a file

I am writing a program that has four classes, Circle,Rectangle,GeometricObject and my main one TestGeometricObject.
I dont understand how to read from another file such as notepad using TestGeometricObject?
I dont need help reading classes I just need help at the moment how can I connect what I have to read another file such as one on notepad, not just this program but for any program I were to write? I hope this made sense...let me know if it did not.
public class TestGeometricObject {
public static void main(String[] args) {
GeometricObject geoObject1 = new Circle();
GeometricObject geoObject2 = new Rectangle();
System.out.println("The two objects have the same area? " +
equalArea(geoObject1, geoObject2));
// Display circle
displayGeometricObject(geoObject1);
// Display rectangle
displayGeometricObject(geoObject2);
}
public static boolean equalArea(GeometricObject object1,GeometricObject object2) {
return object1.getArea() == object2.getArea();
}
public static void displayGeometricObject(GeometricObject object) {
System.out.println();
System.out.println("The area is " + object.getArea());
System.out.println("The perimeter is " + object.getPerimeter());
}
}//end main
public class Circle extends GeometricObject {
private double radius;
public Circle() {
}
public Circle(double radius) {
this.radius = radius;
}
/** Return radius */
public double getRadius() {
return radius;
}
/** Set a new radius */
public void setRadius(double radius) {
this.radius = radius;
}
/** Return area */
public double getArea() {
return radius * radius * Math.PI;
}
/** Return diameter */
public double getDiameter() {
return 2 * radius;
}
/** Return perimeter */
public double getPerimeter() {
return 2 * radius * Math.PI;
}
/* Print the circle info */
public void printCircle() {
System.out.println("The circle is created " + getDateCreated() +
" and the radius is " + radius);
}
}//end
public class Rectangle extends GeometricObject {
private double width;
private double height;
public Rectangle() {
}
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
/** Return width */
public double getWidth() {
return width;
}
/** Set a new width */
public void setWidth(double width) {
this.width = width;
}
/** Return height */
public double getHeight() {
return height;
}
/** Set a new height */
public void setHeight(double height) {
this.height = height;
}
/** Return area */
public double getArea() {
return width * height;
}
/** Return perimeter */
public double getPerimeter() {
return 2 * (width + height);
}
}//end
public abstract class GeometricObject {
private String color = "white";
private boolean filled;
private java.util.Date dateCreated;
/** Construct a default geometric object */
protected GeometricObject() {
dateCreated = new java.util.Date();
}
/** Construct a geometric object with color and filled value */
protected GeometricObject(String color, boolean filled) {
dateCreated = new java.util.Date();
this.color = color;
this.filled = filled;
}
/** Return color */
public String getColor() {
return color;
}
/** Set a new color */
public void setColor(String color) {
this.color = color;
}
/** Return filled. Since filled is boolean,
* the get method is named isFilled */
public boolean isFilled() {
return filled;
}
/** Set a new filled */
public void setFilled(boolean filled) {
this.filled = filled;
}
/** Get dateCreated */
public java.util.Date getDateCreated() {
return dateCreated;
}
public String toString() {
return "created on " + dateCreated + "\ncolor: " + color +
" and filled: " + filled;
}
/** Abstract method getArea */
public abstract double getArea();
/** Abstract method getPerimeter */
public abstract double getPerimeter();
}//end
To read a text file, it is common practice to use a BufferedReader wrapper and FileReader
try {
BufferedReader br = new BufferedReader(new FileReader(new File("yourFile.txt")));
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
br.close();
} catch (IOException e) {
e.printStackTrace();
}

Categories

Resources