Here's my take on creating a set of classes in Java related to geometric shapes.1. Should the shapes be 2dimensional or 3D?
We proceed by asking questions and trying to give reasonable answers to them.
Can we proceed without limiting ourselves to the dimension? Perhaps in some situations we want 2D shapes (triangles, circles, etc.), but perhaps sometimes we would like to consider 3D ones.2. How should we organize the hierarchy?
Are there other dimensions? Well, of course  1D would be a single coordinate, the position on a line or path. 4D? Spacetime for example. Mathematicians often consider higher dimensions, and then if one goes into business applications, one may very well encounter applications with lots more variables, each of which could be taken to be a dimension. Or for good measure, consider the physics of a rigid body: center of mass (3), velocity (3), acceleration (3), time (1), rotation axis (3), rotational velocity (1), rotational acceleration (1), for a grand total of 15 dimensions  and nothing like relativity or quantum mechanics yet.
Sounds like it would be nice to let the dimension be any positive integer.
How about 0? that would be a point. This looks less reasonable, since how can we give any coordinate of a shape if we don't have any coordinates at all.
After all this, we then move on to consider what kind of structure might support arbitrary dimensions of geometric objects. After some thought, you might agree that an array would be nice  with the length of the array equal to the number of dimensions. We can then have 2 or 3 or other dimensional shapes derived from this class, and the dimension array would represent the coordinates of the object in the space of that dimension.
In other words, given the nature of the problem and number of attributes each class requires and how those attributes relate to each other, how should this be organized?
At first blush, from geometry class in high school (or perhaps even earlier), we think of the hierarchy something like this:
 A square is a kind of rectangle
 A cube is a kind of box with a square base
 A box with a square base is a kind of box
 An equilateral triangle is a kind of isosceles triangle
 An isosceles triangle is a kind of triangle
 Everything has some kind of location in a coordinate space
We are often told that the proper question to ask when creating a hierarchy is:
If so, then we should make B the parent class and A the child class.
 A is a B?
This is a good place to start, particularly when confronted with classes and categories that are pretty much new to us.
But in this case, which is why I like to work on this problem in particular, the question seems to be the reverse of how we should proceed.
So here, a cube will require one dimension, a squarebased box would require 2 dimensions and a general box would require 3, so the relationship among these classes should be:
 RectagularPrism (or Box) extends SquarePrism extends Cube
NOTE: This is certainly not the only way to organize a hierarchy of geometric objects. You might want to think about others, and how one might use them in different ways.
3. What should we do, and in what order?
 Select the shapes, or at least select one or two and see where they lead  say:
 circle to sphere
 box to square box to cube
 Select a top class (say ND_Shape, for Nicholas Duchon)  a place for main!
 Select a name that won't be confused with other classes  starting with ND_ is one way to keep names local
 Compare to the use of J for most of the swing classes
 Sometimes this is called a Hungarian notation (Hungarian notation  Wikipedia, the free encyclopedia)
 Think of main in that class (our class ND_Shape) as test code for that class and its children
 code that really uses these classes would have its own main, not using this main
 Any attributes specific to the parent class? location! dimensions? arbitrary (1 or more). Type: double []
 Create a toString method in EVERY class.
 Consider using toString methods of parent classes
 Consider providing other String methods at various levels of the hierarchy, to be used by children String methods for example
 Consider constructors 
 what information do they need?
 are there reasonable defaults? If not, don't provide default constructors  hide them.
 should they use constructors of the parent class? this can be effective
 Test plans should consider the following issues:
 since we are going to be creating a number of classes, we don't need to solve all problems at once!
 create detailed test cases for each new class as they are created
4. On to the code  again, what to do and in what order?
 Start with a top class, and NO BODY, save it with the right name
 Add block comments at the top: file name, date, author, purpose
 This may not be very interesting, but it should compile  if this doesn't compile, there is no reason to write anything else.
 Add main, print "hello world" or some other trivial string  again, if this doesn't work, there is no reason to continue
 Add one or more instance variables (just one if you are a beginner with Java).
 Add a toString method to print the value of the instance variable(s)
 Create a constructor which will give the instance variable(s) values from the parameter list
 Add a line to main to instantiate the class, giving the instance variable(s) interesting values (0 is generally not a good test)
 Create a test plan for this step and execute it
 If the changes are small, the test plan can be very short, but in any case, strive to make it thorough.
 What do you EXPECT the program to do?
 TEST THIS!
 Does the program do what you expected?
 If so, perhaps the program is working.
 If not, you need to figure out why your expectations are different from the actual results  this is the more interesting case because it will force you to learn something.
 Time for a break? This would be a good time  you have made progress!
 Now we are ready to create a child class.
 in this case, perhaps ND_Circle
 Extend the parent class
 Define new attribute(s)
 Define the toString method
 Define constructor(s)
 Use an explicit call to the parent constructor (super), if appropriate
 Note that without such an explicit call, the JVM does an implicit call to the noparameter version of the parent constructor.
 Back to f
 Define new methods
 Back to f
 Back to g until done.
 Be happy  Go get a beer or wine or say hi to your family or something.
You really should notice just how short the main program is.
It consists of lines that instantiate the classes, and then use an implicit call to the class's toString method to print the instance attributes of that class, along with the perimeter, area and/or volume appropriate to that class.
All these instances could be referenced with a variable of the type of the parent class, ND_Shape, as long as only location, perimeter, area and volume were required.
So here's a way of representing the new and inherited variables in each class, and their meanings:
Class 
New Instance Attribute 
Inherited Attributes 
Notes 
ND_Shape 
double [] coordinates 
An array of double of indeterminate size represents the location of the object in a coordinate system the dimension of the coordinate system is equal to the number of elements 2D would use 2 elements 3D would use 3 etc. 

ND_Shape1D 
double length 
double [] coordinates  In 1 dimension, only length makes much sense but one could add open and closed sets of various kinds and things could actually get very complicated consider sets like the Cantor set or the set of all rational numbers. 
ND_Circle 
double radius 
double [] coordinates  center and radius are enough in 2D but in higher dimensions, specifying a circle would require also specifying the 2D surface containing it 
ND_Sphere 
double radius 
double [] coordinates  same as circle, but the area is different has a volume and does not have a perimeter in higher dimensions, need specifications of a containing 3D object 
ND_TriEq 
double side 
double [] coordinates  an equilateral triangle, length of one side
is enough 
ND_TriIs 
double side2 
double side double [] coordinates 
an isosceles triangle, an additional side side would be the pair of equal sides, side2 is unequal one 
ND_Tri 
double side3 
double side2 double side double [] coordinates 
a general triangle  dimensions of three
sides are enough 
ND_Cube 
double side 
double [] coordinates  a box with all sides the same length, only
one dimension needs to be set all angles are right angles. 
ND_SquarePrism 
double side2 
double side double [] coordinates 
two dimensions are the same, the third (say
height) varies 
ND_RectangularPrism 
double side3 
double side double side2 double [] coordinates 
a box with all three sides varying all angles 90 degrees 
The constructors are not explicitly listed in this table, and all of them use coordinates as the final set of variables.
You should note that nearly all the constructors start with a call to their parent class constructors. This is a convenient way to use the parent class constructors to initialize the attribute(s) they handle, making the child constructor's job a local issue, and much shorter.
Note that each class has its own toString method  a nice presentation of the information for that class, including perimeter, area and/or volume as is appropriate for that class.
Class 
New Instance Methods 
Overridden Inherited Methods 
Notes 
ND_Shape 
double perimeter double area double volume String toStringLoc 
String toString  First three methods are place holders all return 0 toString adds "Center" to location string this method puts the location in parentheses, nicely 
ND_Shape1D 
String toString  
ND_Circle 
double perimeter double area String toString 
returns area and perimeter (circumference) of
a circle only the radius is needed for those calculations 

ND_Sphere 
double area double volume String toString 
surface area and volume of a sphere with a
given radius 

ND_TriEq 
double heron double areaHeron 
double perimeter double area String toString 
perimeter and area of an equilateral triangle
based on the length of the side Heron's formula applies to all triangles, so this is the natural class to have it. the code uses a dedicated formula and checks against the Heron result. Call to Heron with 3 equal values 
ND_TriIs 
double perimeter double area double areaHeron String toString 
As the equilateral triangle case, but only
two sides are the same. The call to Heron use two equal values, and one different one 

ND_Tri 
double perimeter double area String toString 
The area uses the Heron formula defined in
equilateral triangle class. 

ND_Cube 
double area double volume String toString 
one dimension is enough to compute area and
volume. this could done the same Heron's formula is used for triangles, but the basic formulas for a box hardly warrant the effort. 

ND_SquarePrism 
double area double volume String toString 
See the comments on a cube, here two sides are the same, the third is allowed to be different 

ND_RectangularPrism 
double area double volume String toString 
See the cube comments, here all three sides of the box can be different. 