# Calculator for the area of various 3D figures, using abstract classes and inheritance

I am a Java newbie, and they have just recently taught us abstract classes and inheritance. While I was practising, I wondered whether I can make multiple instances of the same abstract method in different classes. (We didn't go that far, and my knowledge about this is what I have gleaned during our professor writing code in front of us.) My curiosity led me to write this code, that I have posted here. It compiles and runs fine, AFAIK; but, I would like this to be simpler and more succinct, if possible.

import java.math.*;
import java.util.*;

abstract class Figure{
// I cant have 2 constructors with same      parameters it seems.
// so side1 has to float otherwise it creates an ambiguity error with
final double PI = 3.14;
double side, height,base;
float side1;
Figure(float s1)
{
side1 = s1;//cube
}
Figure(double h1, int r1)// cone uses side instead of height to resolve ambiguity
{
height = h1;//cone
}
Figure(int r1)
{
}
Figure(int r1,double h1)
{
height = h1;//cylinder
}
Figure(double h1,double b1)
{
base = b1;
height = h1;//pyramid
}
abstract double areaCalculator();

}

class Cube extends Figure{

double result;
Cube(float s1)
{
super(s1);
}

double areaCalculator()
{
result = 6 * Math.pow(side1,2);
return result;
}

}

class Cone extends Figure{

double result;
Cone(double h1, int r1)
{
super(h1,r1);
}

double areaCalculator()
{
return result;
}

}

class Sphere extends Figure{

double result;
Sphere(int r1)
{
super(r1);
}

double areaCalculator()
{
result = PI * 4.0 * Math.pow(radius,2);
return result;
}

}

class Cylinder extends Figure{

double result;
Cylinder(int r1, double h1)
{
super(r1, h1);
}

double areaCalculator()
{
result = (2.0 * PI * Math.pow(radius,2)) + (2.0 * PI * radius * height);
return result;
}

}

class Pyramidsqbase extends Figure{

double result;
Pyramidsqbase(double b1, double h1)
{
super(h1,b1);
}

double areaCalculator()
{
result = Math.pow(base,2) + (2.0 * base * height);
return result;
}

}

class Newsurfaceareacalc2{

public static void main(String args[])
{
double result,side, height, base;
float side1;
Scanner sc = new Scanner(System.in);

System.out.println("Surface area Calculator:");
System.out.println("1 for cube, 2 for cone, 3 for sphere, 4 for cylinder, 5 for square-base pyramid.");
choice = sc.nextInt();

switch(choice)
{
case 1: System.out.println("Enter value of side of cube:");//cube
side1 = sc.nextFloat();
Cube c1 = new Cube(side1);
result = c1.areaCalculator();
System.out.println("Result is "+ result);
break;

case 2: System.out.println("Enter value of radius of cone:");//cone
System.out.println("Enter value of height of cone:");
height = sc.nextDouble();
Cone c2 = new Cone(height, radius);
result = c2.areaCalculator();
System.out.println("Result is "+ result);
break;

case 3: System.out.println("Enter value of radius of sphere:");//sphere
result = s2.areaCalculator();
System.out.println("Result is "+ result);
break;

case 4: System.out.println("Enter value of radius of cylinder:");//cylinder
System.out.println("Enter value of of height of cylinder:");
height = sc.nextDouble();
Cylinder c3 = new Cylinder(radius, height);
result = c3.areaCalculator();
System.out.println("Result is "+ result);
break;
case 5: System.out.println("Enter value of base in pyramid");//pyramid
base = sc.nextDouble();
System.out.println("Enter value of height in pyramid:");
height = sc.nextDouble();
Pyramidsqbase p1 = new Pyramidsqbase(base, height);
result = p1.areaCalculator();
System.out.println("Result is "+ result);
break;

default: System.out.println("Error.");
}

}

}


1. I don't think there's a point in having multiple constructors in the Figure class. I don't see why it should have any fields at all. I'd suggest to store the data in its subclasses (so that each subclass has only the fields it actually uses. It makes no sense for the Cube to have the radius field, for instance). Actually, the Figure could be an interface with just one method for computing the area.

2. I would also create methods to read the input for each specific figure and print the result (so that each case clause just calls the corresponding method). It will also help to get rid of a bunch of variables declared at the top of the main method (they reduce the code readability because their declaration point is far from their first usage. Moreover, some of them are never used depending on the user input).

I wondered whether I can make multiple instances of the same abstract method in different classes.

You cannot make instances of methods. You can only make instances of classes. These instances are objects. Objects have methods which are defined in their class.

Classes can extend each other (one direction). This is called inheritance.

In java we have two different kinds of inheritance:

1. Method definition inheritance

You can declare abstract methods where you only provide the signature of the method but no content. This type of inheritance can be provided by abstract classes or interfaces (the latter is preferred).

interface Animal{
// defines that every animal is able to make sound,
// even fish... ;o)
String makeSound();
}

class Dog implements Animal{
@Overwrite
public String makeSound();{
return "Wouff";
}
}
class Cat implements Animal{
@Overwrite
public String makeSound();{
return "Meauw";
}
}


it gets funny when we use this:

List<Animal> animals = Arrays.asList(new Dog(), new Cat());
for(Animal animal : animals)
// each animal gives its own sound!
System.out.println(animal.makeSound());


output is:

  Wouff
Meauw

2. Behavior Inheritance

This is provided by base classes which could, but may not be abstract. The Point is that the method(s) which will be inherited by the child class are not abstract, this means they have a content.

class BaseClass{
public String commonBehavior(){
return "common behavior of BaseClass called in "+getClass();
}
}

class Child1 extends BaseClass {
// may have own behavior, but not needed for the demo
}

class Child2 extends BaseClass {
// same here
}


now we can call the common behavior on the child classes although they did not have any code of their own:

System.out.println(new  Child1().commonBehavior());
System.out.println(new  Child2().commonBehavior());


The output of this is:

 common behavior of BaseClass called in Child1
common behavior of BaseClass called in Child2


Try it out.