Access subclass fields from a base class in Java - java

I have a base class called Geometry from which there exists a subclass Sphere:
public class Geometry
{
String shape_name;
String material;
public Geometry()
{
System.out.println("New geometric object created.");
}
}
and a subclass:
public class Sphere extends Geometry
{
Vector3d center;
double radius;
public Sphere(Vector3d coords, double radius, String sphere_name, String material)
{
this.center = coords;
this.radius = radius;
super.shape_name = sphere_name;
super.material = material;
}
}
I have an ArrayList that contains all Geometry objects and I want to iterate over it to check whether the data from a text file is read in correctly. Here is my iterator method so far:
public static void check()
{
Iterator<Geometry> e = objects.iterator();
while (e.hasNext())
{
Geometry g = (Geometry) e.next();
if (g instanceof Sphere)
{
System.out.println(g.shape_name);
System.out.println(g.material);
}
}
}
How do I access and print out the Sphere's radius and center fields?
Thanks in advance :)

If you want to access properties of a subclass, you're going to have to cast to the subclass.
if (g instanceof Sphere)
{
Sphere s = (Sphere) g;
System.out.println(s.radius);
....
}
This isn't the most OO way to do things, though: once you have more subclasses of Geometry you're going to need to start casting to each of those types, which quickly becomes a big mess. If you want to print the properties of an object, you should have a method on your Geometry object called print() or something along those lines, that will print each of the properties in the object. Something like this:
class Geometry {
...
public void print() {
System.out.println(shape_name);
System.out.println(material);
}
}
class Shape extends Geometry {
...
public void print() {
System.out.println(radius);
System.out.println(center);
super.print();
}
}
This way, you don't need to do the casting and you can just call g.print() inside your while loop.

You have to cast (specifically, downcast):
((Sphere) g).radius

I agree with rwhat, but instead of implementing your own print() function, it might benefit you (and be more Object Oriented) to avoid the downcasts by overriding the toString() function.
public class Geometry
{
String shape_name;
String material;
public Geometry()
{
System.out.println("New geometric object created.");
}
public String toString() {
StringBuilder result = new StringBuilder();
result.append("Shape name: " + shape_name + "\t");
result.append("Material: " + material + "\t");
return result.toString();
}
public static void check (Geometry[] gList) {
for (Geometry g: gList) {
System.out.println(g.toString());
}
}
Note the check() doesn't care whether g is a Sphere or a Cube. This will help minimize the calls to instanceof.
Over in Sphere...
public class Sphere extends Geometry
{
Vector3d center;
double radius;
public Sphere(Vector3d coords, double radius, String sphere_name, String material)
{
this.center = coords;
this.radius = radius;
shape_name = sphere_name;
super.material = material;
}
public String toString() {
StringBuilder result = new StringBuilder();
result.append("Radius: " + radius + "\t");
result.append("Center: " + center.toString() + "\t");
result.append(super.toString());
return result.toString();
}
}
Any new shape (e.g., Cone) would benefit by having the toString() function, but lacking it would just print out Geometry's version.

use instanceof and Cast to the desired subclass. You might want to make those fields public or the standard idiom of private fields with getters and setters too.

Related

How can I access a method of a class from a generic method

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.

How to call a method from all implement java

I have one interface
public interface GeometricObject {
public String getInfo();
}
And I have 2 classes, which implement the above interface.
public class Circle implements GeometricObject {
#Override
public String getInfo() {
return "Circle[center,radius]";
}
}
public class Triangle implements GeometricObject {
#Override
public String getInfo() {
return "Triangle[p1,p2,p3]";
}
}
And now I have this class to show all info that:
public class shapeUtils{
public String printInfo(List<GeometricObject> shapes) {
//code here
}
}
How can I call that method in all implements to that list
e.g.
Circle:
Circle[(1,2),r=3]
Circle[(5,6),r=2]
Triangle:
Triangle[(1,2),(2,3),(3,0)]
Triangle[(-1,-3),(-5,3),(0,0)]
Just call it
for (GeometricObject shp : shapes) {
System.out.println (shp.getInfo());
}
I you want more simplicity.
shapes.forEach(shape -> System.out.println(shape.getInfo()));
First you have to add the fields that you need to your shapes. For example in the triangle you need p1, p2, p3. They must be part of the class if you want to get the right values printed.
E.g:
public class Circle implements GeometricObject {
private double center;
private double radius;
#Override
public String getInfo() {
return "Circle[ " + this.center + ", " + this.radius + " ]";
}
// Getters and setters
}
You do the same for all the shapes.
You can fill a list with objects like this:
java.util.List<GeometricObject> shapes = new ArrayList<>();
Circle circle = new Circle(); // Initialize it
circle.setCenter(2); // Set the values
circle.setRadius(2);
shapes.add(circle); // Add it to the list
// Add some more objects into the list...
// Print them:
for (GeometricObject shape : shapes) {
System.out.println(shape.getInfo());
}

How do I store objects of sub classes in array?

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());
}
} }

Regarding casting in Java within class hierarchies [duplicate]

I have a base class called Geometry from which there exists a subclass Sphere:
public class Geometry
{
String shape_name;
String material;
public Geometry()
{
System.out.println("New geometric object created.");
}
}
and a subclass:
public class Sphere extends Geometry
{
Vector3d center;
double radius;
public Sphere(Vector3d coords, double radius, String sphere_name, String material)
{
this.center = coords;
this.radius = radius;
super.shape_name = sphere_name;
super.material = material;
}
}
I have an ArrayList that contains all Geometry objects and I want to iterate over it to check whether the data from a text file is read in correctly. Here is my iterator method so far:
public static void check()
{
Iterator<Geometry> e = objects.iterator();
while (e.hasNext())
{
Geometry g = (Geometry) e.next();
if (g instanceof Sphere)
{
System.out.println(g.shape_name);
System.out.println(g.material);
}
}
}
How do I access and print out the Sphere's radius and center fields?
Thanks in advance :)
If you want to access properties of a subclass, you're going to have to cast to the subclass.
if (g instanceof Sphere)
{
Sphere s = (Sphere) g;
System.out.println(s.radius);
....
}
This isn't the most OO way to do things, though: once you have more subclasses of Geometry you're going to need to start casting to each of those types, which quickly becomes a big mess. If you want to print the properties of an object, you should have a method on your Geometry object called print() or something along those lines, that will print each of the properties in the object. Something like this:
class Geometry {
...
public void print() {
System.out.println(shape_name);
System.out.println(material);
}
}
class Shape extends Geometry {
...
public void print() {
System.out.println(radius);
System.out.println(center);
super.print();
}
}
This way, you don't need to do the casting and you can just call g.print() inside your while loop.
You have to cast (specifically, downcast):
((Sphere) g).radius
I agree with rwhat, but instead of implementing your own print() function, it might benefit you (and be more Object Oriented) to avoid the downcasts by overriding the toString() function.
public class Geometry
{
String shape_name;
String material;
public Geometry()
{
System.out.println("New geometric object created.");
}
public String toString() {
StringBuilder result = new StringBuilder();
result.append("Shape name: " + shape_name + "\t");
result.append("Material: " + material + "\t");
return result.toString();
}
public static void check (Geometry[] gList) {
for (Geometry g: gList) {
System.out.println(g.toString());
}
}
Note the check() doesn't care whether g is a Sphere or a Cube. This will help minimize the calls to instanceof.
Over in Sphere...
public class Sphere extends Geometry
{
Vector3d center;
double radius;
public Sphere(Vector3d coords, double radius, String sphere_name, String material)
{
this.center = coords;
this.radius = radius;
shape_name = sphere_name;
super.material = material;
}
public String toString() {
StringBuilder result = new StringBuilder();
result.append("Radius: " + radius + "\t");
result.append("Center: " + center.toString() + "\t");
result.append(super.toString());
return result.toString();
}
}
Any new shape (e.g., Cone) would benefit by having the toString() function, but lacking it would just print out Geometry's version.
use instanceof and Cast to the desired subclass. You might want to make those fields public or the standard idiom of private fields with getters and setters too.

Abstract Classes error

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.

Categories

Resources