Win a copy of Mesos in Action this week in the Cloud/Virtualizaton forum!

# Are my classes shaped correctly?

Andre Brito
Ranch Hand
Posts: 95
Hi folks.
Again, I don't know how to shape my classes. So, here is the "problem":

I have to use inheritance. I have the Quadrilatero class, that is the superclass for all the classes. Then, I have + 4 classes: Quadrado (Square), Retangulo (Rectangule), Trapezio (Trapezium) and Losango (losangle, like a kite) and all of these for extends Quadrilatero (4 lines shapes).

First, the superclass:

Then, my others:

But then, the formula to calculate the area of Trapezium is different, and the parameters for super too! So, I thought about override the method calculateArea(), from superclass, and make another constructor for superclass, accpeting 3 parameters: the height, the larger base and the another base. Another 2 methods in Trapezium set() and get() for some of the bases and that's it.

Is this ok or I need to shape it better?
Can you guys help me with some ideas?

Thanks folks!

Andre Brito
Ranch Hand
Posts: 95
Hi! I'm sorry, but I thought again, and it would be better if I create another superclass that extends from Quadrilatero, like Shapes2 and Shapes3? So, Trapezium would extends Shapes3 and the other Shapes2?

Rob Spoor
Sheriff
Posts: 20531
54
A square/rectangle have very little to do with trapeziums, parallellograms and "kites" except for the 4 sides, so I wouldn't let any of them extend another.

Another thing: a square is a rectangle (with equal sides), not vice versa. So you'd better switch them around, and have only one value for the square:

Andre Brito
Ranch Hand
Posts: 95
Rob,

Thank you so much for you answer!
I've grab my Deitel's book and looked at this excescise.
So, I think that he mentioned that Quadrilatero = 4 sides shapes. That's the reason that I've made Trapezium and "kites" subclasses from Quadrilatero. And kites have 2 values (the D and d), so, I guess it could stay subclass from Quadrilatero, don't you think the same? I'll just have to override the method calculateArea(). The problem is with trapezium...

I liked very much your solution... relly, and I don't think it's incorrect. But is there another way to do it?

Like, my diagram:

Diagram

As you can see, I don't know what to do with Trapezio (Trapezium).
Do you have another idea?

Andre Brito
Ranch Hand
Posts: 95
Hi again.
I did what you said, but where goes Trapezium?
I mean... I want to use inheritance, so I need to have a superclass, like Shape. But what does this class have?
The right inheritance would be:

Shape -> Rectangle -> Square
Shape -> Trapezium ??

Can I raise up this (I don't know the right expression!)?

Thanks, I'm sorry my English and the flooding

Rob Spoor
Sheriff
Posts: 20531
54
Originally posted by Andre Brito:
I've grab my Deitel's book and looked at this excescise.
So, I think that he mentioned that Quadrilatero = 4 sides shapes. That's the reason that I've made Trapezium and "kites" subclasses from Quadrilatero. And kites have 2 values (the D and d), so, I guess it could stay subclass from Quadrilatero, don't you think the same? I'll just have to override the method calculateArea(). The problem is with trapezium...

Quadrilatero could very well be the abstract base class of all 4-sided shapes. I highlighted abstract because a 4-sided shape doesn't really make sense without describing it further. Because it's abstract, calculateArea() can be abstract - only the subclasses know how to calculate the area.

For rectangle (and square) it's easy: x * y.

For kite it's also easy: x * y / 2. This works because you can see the kite as four triangles, created by drawing the X and Y lines between corners. Then X * Y makes up the area of the containing rectangle, duplicating each triangle. See Kite

For trapezium you can use Trapezoid.

Other shapes you could use are Parallellogram, which could be a parent class of Rectangle, and Rhombus. This one has one small problem - it could be a subclass of both Kite and Parallellogram.

So the hierarchy would be something like this:

One thing you have to think about is: what do X and Y mean for these shapes. For parallellogram (and subclasses) you need the base size (X) and the height between parallel sides (Y). For rectangle and square, Y is also the size of the other sides.
For trapezoid you need the base side, the other horizontal side, and the distance betweent hem.
For Kite you need the diagonals.

Possibly you shouldn't define X and Y for Quadrilatero but for the specific subclasses, as some need two, some need three, and some (for quadrilateros without any special properties) you need all four sides, plus even the angles between them.

Andre Brito
Ranch Hand
Posts: 95
Rob,

And it's ok to confuse things, 'cause their name are in portuguese... I only noticed that right now hehehe. Sorry

After think a little and talk with a friend of my (from here, Brazil), I made the class diagram:

And it'll stay this way because I believe that it's a good shape, don't you think? Please, if you have any ideas, just put it down here! Hehe.
BTW, class Quadrilatero is abstract. The method calculateArea() is abstract and that way, trapezoid has its method and Retangulo has its method.

One thing that I'm not understanding is: what's the advantage of my superclass have 1 abstract method? Like... if I can override it, wouldn't be better if I had to write only 1 more method (the one that would override) instead I had to write 1 assignature and 2 methods different?

I'm sorry my english... if you didn't understand, please, notice.

Thanks!

Rob Spoor
Sheriff
Posts: 20531
54
Originally posted by Andre Brito:
After think a little and talk with a friend of my (from here, Brazil), I made the class diagram:

And it'll stay this way because I believe that it's a good shape, don't you think? Please, if you have any ideas, just put it down here! Hehe.
BTW, class Quadrilatero is abstract. The method calculateArea() is abstract and that way, trapezoid has its method and Retangulo has its method.

Technically a Paralelogramo is not a Rectangulo but it's the other way around. And Losango may have a similar way of calculating the area, it is nowhere near being a Rectangulo. Don't create inheritence because it's easy for implementation; create inheritence because it should be there logically.

One thing that I'm not understanding is: what's the advantage of my superclass have 1 abstract method? Like... if I can override it, wouldn't be better if I had to write only 1 more method (the one that would override) instead I had to write 1 assignature and 2 methods different?

With the abstract method, you can call the "calculateArea" method on any shape - it doesn't matter if it's a Rectangulo, Losango, Trapezio or any other. They all have the method, they all know how to calucate the area correctly, all you do is call the method.

Andre Brito
Ranch Hand
Posts: 95
Ok Rob, first of all, thanks.

I know that I can call the method from any class... but how can I call the method that is not implemented? When do I use abstract method? Why I can't keep the concrete and override the new one when this is the easier way to do?

Rob Spoor
Sheriff
Posts: 20531
54
Originally posted by Andre Brito:
but how can I call the method that is not implemented? When do I use abstract method?

Since the Quadrilatero will be abstract, you cannot instantiate it. All concrete subclasses must implement the method, and when you call the method with a reference type of Quadrilatero, the actual class of the object will determine the method implementation. So if it is a Rectangulo, then Rectangulo's calculateArea() method is called.

Why I can't keep the concrete and override the new one when this is the easier way to do?

Well you can, but then the question is: what is the area of a Quadrilatero? And do you want to allow instances of Quadrilatero itself to be created?

Campbell Ritchie
Sheriff
Posts: 48968
60
I really ought to have come in earlier. This came up last year; I found a thread I was supposed to have posted on on 17th April 2007, but for some peculiar reason my post doesn't come up on search.

As far as I remember, people said that it is true that "a square is a rectangle," but a "Square object is not a Rectangle object," and quoted sources rather like this one which I think is by Robert Martin, and something similar by Barry Burd which I can't now find.
What people were pointing out is the bit aboutor similar.

What this means is that the getArea() setHeight() and setWidth() methods do not behave the same in Rectangle and Square, sois liable to breach Liskov's principle, and shouldn't be used as inheritance.

Now I know we are all taught as beginners that inheritance follows the basis of "public class Foo extends Bar," but "public class Foo implements Bar" might be a lot better. It is actually rather like what Barry Burd suggested (as far as I remember).

This suggests that all the shapes ought to implement a Shape interface, like thisand you could create other interfaces likeThis would mean implementing different interfaces like thisYou can have ShapeWithTwoSizes as a sub-interface of Shape or not; it will work both ways probably without any other changes to your code.

You can call them like thisI hope that is of some use.
I have made a few small changes to this post.

Andre Brito
Ranch Hand
Posts: 95
OMG! I'm sorry for being out for a while...
Thanks to both of you guys... I'm really a dumn when talking about shaping classes... sometimes I guess that for me it can be very confusing!
I hope that when I finnish my books, this problems get easier to solve

But thank you guys very much!
See you around!