How do I do something like this? I want to take command line arguments like Circle 10 or Rectangle 20 30 and create objects of the corresponding classes.
class Circle{
//Some lines here
}
class Rectangle{
//Some lines here
}
public class Perimeter{
public static void main(String[] args) {
for(int i=0; i< args.length; i++){
String shape = args[0];
shape curr_shape = new shape();
System.out.println(curr_shape.getPerimeter( <arguments> ));
}
}
}
You can use Class.forName() and reflection to create an instance, like #Milgo proposed, but I would recommend to create a simple switch/case. Your task looks like some training, so probably that would be best option for you.
Object form;
switch (type) {
case "Circle":
form = new Circle();
break;
case "Rectangle":
form = new Rectangle();
break;
}
Although you could use reflection (ie the dark arts), you can do it with minimal code if all shapes have the same constructor signature of say List<Double> (which includes integers like your example):
private static Map<String, Function<List<Double>, Shape>> factories =
Map.of("Circle", Circle::new, "Rectangle", Rectangle::new); // etc
public static Shape createShape(String input) {
String[] parts = input.split(" ");
String name = parts[0];
List<Double> dimensions = Arrays.stream(parts)
.skip(1) // skip the name
.map(Double::parseDouble) // convert String terms to doubles
.collect(toList());
return factories.get(name).apply(dimensions); // call constructor
}
interface Shape {
double getPerimeter();
}
static class Rectangle implements Shape {
private double height;
private double width;
public Rectangle(List<Double> dimensions) {
height = dimensions.get(0);
width = dimensions.get(1);
}
#Override
public double getPerimeter() {
return 2 * (height + width);
}
}
static class Circle implements Shape {
double radius;
public Circle(List<Double> dimensions) {
radius = dimensions.get(0);
}
#Override
public double getPerimeter() {
return (double) Math.PI * radius * radius;
}
}
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.
The question is to create objects of both sub classes and store them in an array .
So I create a abstract Super class and made a method area abstract after that I created the two sub classes and implemented that method on the main method I declared array and given the values this is it. I am new here so sorry if I'm asking it in wrong way.
And yes the output should be the area and types of two figure.
package Geometric;
public abstract class GeometricFigure {
int height;
int width;
String type;
int area;
public GeometricFigure(int height, int width) {
//super();
this.height = height;
this.width = width;
}
public abstract int area();
}
package Geometric;
public class Square extends GeometricFigure {
public Square(int height, int width) {
super(height,width);
}
public int area(){
return height * width;
}
}
package Geometric;
public class Triangle extends GeometricFigure {
public Triangle(int height, int width) {
super(height ,width);
}
public int area() {
return (height*width)/2;
}
}
package Geometric;
public class UseGeometric {
public static void main(String args[]) {
GeometricFigure[] usegeometric = { new Square(12, 15), new Triangle(21, 18) };
for (int i = 0; i < usegeometric.length; i++) {
System.out.println(usegeometric[i]);
usegeometric[i].area();
System.out.println();
}
}
}
You already are storing both elements in an array, I think your question is more related to this part:
usegeometric[i].area();
System.out.println();
You get the area of both elements, but you don't assign it to a variable, and you don't do anything with it. Change those lines of code to this:
System.out.println("Area: " + usegeometric[i].area());
EDIT:
Geometric.Square#19dfb72a Geometric.Triangle#17f6480
This is the kind of output you can expect because you didn't overwrite the toString method in your classes.
If you don't, it will take the inherited version of Object, which prints this information
--
In your Square class, add this:
public String toString() {
return "Square - area = " + area();
}
or something similar, depending on what you want to be printed. (And a similar adjustment to your Triangle class).
At this time, you are printing Object's version of toString, since you didn't provide a new one. By overwriting that method, you should get the output you want after turning your loop into:
for (int i = 0; i < usegeometric.length; i++) {
System.out.println(usegeometric[i]);
}
What println actually does, is not print the object itself, but a String representation of the object, which is provided by the toString method.
public class UseGeometric {
public static void main(String[] args) {
// TODO Auto-generated method stub
GeometricFigure[] usegeometric = { new Square(12, 15), new Triangle(21, 18) };
for (int i = 0; i < usegeometric.length; i++) {
System.out.println("Area is: " + usegeometric[i].area());
}
} }
Image of Description
The aim is to have the user select a shape (Square, Triangle or Circle) and then enter a boundary length. Once this information has been input I can then calculate the perimeter and area of their choice.
The problem is I don't want to create new variables for the length and area in each class if I don't have to and would rather have the variables declared and then passed into the classes if I can.
Basically I don't want to do it like this,
class square {
double bLength;
double area;
}
class triangle {
double bLength;
double area;
}
class circle {
double bLength;
double area;
}
Can I declare them outside of the classes and then have the classes use/inherit them or anything?
I must apologise for such a basic question, I am quite new to Java and I can't really think around this one.
The classic solution is to use inheritance:
class Shape {
double bLength;
double area;
Shape(double bLength, double area) {
this.bLength = bLength;
this.area = area;
}
}
class Square extends Shape {
Square(double bLength, double area) {
super(bLength, area);
}
// additional field, methods...
}
// same for the other shapes
You can use inheritance for this problem in following way :
Declare a class called Shape from which all other classes would inherit
public class Shape {
public double length = 0;
public abstract double GetPerimeter();
public abstract double GetArea();
public Shape(double length) {
this.length = length;
}
}
Then have your specialized classes. E.g. :
public class Circle extends Shape {
public Circle(double length) {
super(length);
}
public double GetPerimeter() {
// Implement the perimeter logic here
}
public double GetArea() {
// Implement the area logic here
}
}
Do this for all classes. This way you have the variable in only one class, and all others inherit from it.
EDIT
If you want even further optimization (for instance, you don't want function call overhead), something like perhaps
public class Shape {
public double length = 0;
public double perimeter= 0;
public double area= 0;
public Shape(double length, double perimeter, double area) {
this.length = length;
this.perimeter= perimeter;
this.area = area;
}
}
public class Circle extends Shape {
public Circle(double length) {
super(length, 2 * Math.PI * length, Math.PI * length * length);
}
}
I'm trying to understand Java by trying several things out. I'm using two classes in the same package. One is called Box, the other one is called TestBox. I want to calculate the area of the company box using calculateArea(). This function is in another class TestBox. However the function calculateArea in Box does not respond to the function in TestBox. I'm missing a link between these two classes. This seems like a simple problem, but I have not found the solution yet. Can someone please help me out?
package box;
public class Box {
int length;
int width;
public static void main(String[] args) {
Box company = new Box();
company.length = 3;
company.width = 4;
int area = company.calculateArea();
}
}
package box;
public class TestBox {
int length;
int width;
int calculateArea(){
int area = length * width;
System.out.println("Area= " + area);
return area;
}
}
I think you have to clarify a bit what is your design, I mean what the classes Box and TestBox should do, moreover I advice use to use an IDE such as Eclipse or Intellij Idea helping you with syntax highlight and founding possible errors.
What you are dealing with is the encapsulation, that is
packing of data and functions into a single component.
so it is feasible that the area of the box is calculated by the Box class itself.
About your code, a possible solution could be:
package com.foo;
public class Main {
public static void main(String[] args) {
Box box = new Box(3, 4);
int area = box.calculateArea();
System.out.println("Box area is: " + area);
}
}
class Box {
private int l;
private int w;
Box(int length, int width) {
l = length;
w = width;
}
int calculateArea() {
return l * w;
}
}
Another possible approach could be
package com.foo;
public class Main {
public static void main(String[] args) {
Box box = new Box(3, 4);
TestBox testBox = new TestBox();
int area = testBox.calculateArea(box);
System.out.println("Box area is: " + area);
}
}
class Box {
private int l;
private int w;
Box(int length, int width) {
l = length;
w = width;
}
public int getLength() {
return l;
}
public int getWidth() {
return w;
}
}
class TestBox {
int calculateArea(Box box) {
return box.getLength() * box.getWidth();
}
If you want to have a separate class doing the job, but it is something I do not like, the function computing the area is related to the box and works on box variables, I prefer the first one, but it should be better to have more details in case.
I hope it helps.
As per the below approach, you need to make parameterized constructor where you can pass the value of length and width at the time of creating TestBox object. You also need to create a default constructor for future save in case if later you only want to create default TestBox object like new TestBox();
You can calculate area in you TestBox class and than return the value in the Box class. You don't need to create separate length and width variable in Box class and no need to create a object of Box.
package box;
public class Box {
public static void main(String[] args) {
TestBox company = new TestBox (3,4);
int area = company.calculateArea();
}
}
package box;
public class TestBox {
private int length;
private int width;
TestBox()
{
}
TestBox(int l, int w)
{
this.length = l;
this.width = w;
}
public int getLength() {
return length;
}
public int getWidth() {
return width;
}
int calculateArea(){
int area = length * width;
System.out.println("Area= " + area);
return area;
}
}
public static void main(String[] args) {
TestBox company = new TestBox();
company.length = 3;
company.width = 4;
int area = company.calculateArea();
}
}
Could someone explain to me how reference (non-primitive) data types works? Mainly how to input data into them and how to check what data they are holding?
Could you use this code as an example please.
public class Example{
public static void main(String [] args){
Circle c= new Circle();
System.out.println():
}
}
public class Circle{
Circle round;
public Circle(){
}
public Circle numPlacment(){
round=new Circle(2); //I would like circle to contain the value of '2'
return round;
}
public String toString(){
StringBuilder b= new StringBuilder();
b.append(round);
return String.format("%4s",b);
}
}
Your code is somewhat nonsensical. It may be easier just to look at how it's supposed to be done:
public class Example{
public static void main(String [] args) {
// create a new circle with radius 2
Circle c= new Circle(2);
// Print that circle
System.out.println(c);
}
}
class Circle {
// The instance variable that stores the radius for this circle
double radius;
// Create a new Circle given a radius
public Circle(double radius) {
// assign the given radius parameter to the instance variable
this.radius = radius;
}
public String toString() {
StringBuilder b= new StringBuilder();
b.append(radius);
return String.format("%4s",b);
}
}