![]() ![]() 16 December 2000 ![]() |
![]() |
Into Java, Part 12
Last time we discussed how to override a method, an OOP (Object Oriented
Programming) technique commonly used, a method that override another is a method in one or several subclasses
that hides access to a method implemented in a superclass. Overriding is also sometimes named shadowing, a method
shadows another one, hides that one. But since shadowing also has another meaning, a lot more used, I do never
use that term on overriding. This time we continue the theory part of these columns with a brief discussion on
overloading and polymorphism. |
Is that bad or good? I consider it good, it is always good to have
some choices to pick from. You are the one to make a decision from the very beginning, which one to pick. I will
not discuss that part to much, but if you from the beginning know that the resulting
Vector
will be of a certain amount, make it that big
then, with a 10% extra for growth. If you know that it will grow very slowly, set the increment capacity to something
reasonable, else the Vector
will
double itself every time it comes to the upper limit.
Does a Vector
have an upper limit? Yes, since under the hood it simply is an array, an Object[]
, and arrays can not grow,
but the Vector
has some
helper methods hidden to take care of that. Not to stray away from the topic, polymorphism, I promise to dig deeper
into the important area of data structures next time. (Yes, I know I said there would be a look under the hood
on Vector, but due to my studies and personal matters I have not had the time to write that much. I am sorry!)
There are other examples of polymorphism in the Vector class, a
few examples are:
add(int index, Object element)
|
|
add(Object o)
|
only in Java1.2 and later |
addAll(int index, Collection c)
|
addAll(Collection c)
|
only in Java1.2 and later |
|
indexOf(Object elem)
|
indexOf(Object elem, int index)
|
||
lastIndexOf(Object elem)
|
lastIndexOf(Object elem, int index)
|
||
remove(int index)
|
remove(Object o)
|
only in Java1.2 and later |
|
toArray()
|
toArray(Object[] a)
|
only in Java1.2 and later |
|
|
String
does certainly not have the record, but still the method
valueOf
has nine signatures.Whenever you create a class and figures out that a method can or
should be called with different arguments from time to time, overloading can be the way to solve the issue. It
is always easier to remember only a few method names, so make the few methods accept the parameters reasonable
under several signatures.
remove
of
the Vector
class. And a
few columns back we discussed the listener model.Think of a listener that will respond to a double click on a shape,
if we clicked a shape it shall be removed from the vector. The question is, who shall act as the listener? The
shapes? The canvas? Or the application itself? Any one is possible, but a few things lead us to pick the PaintPanel
; it has a
MouseAdapter
to use, and it holds the storage of the
shape objects. Let us add this feature to the PaintPanel then.
PaintShape
class. Any PaintShape
will be equipped with a method that replies to the question
"is this you?", "Do you contain this x,y point?"Please, look the Java API up, => Index => C => contains ;
you find a lot of contains there. All of them do the job we would like to, but which one is
best suited? So far "none"! That is because our PaintShape
does not inherit from one of these classes seen. But one of them may be
used, the java.awt.Rectangle. Rectangle
is
a humble class that corresponds to a rectangular area and can answer our question (any shape we make can be said
to cover a rectangular area).
Our problem so far is that there is no
Rectangle
in PaintShape
, let us add one, a simple declaration
among the other declared variables. Now we must figure out were to instantiate it. The obvious place is when we learn to know the stop coordinate, since we know the starting point from the very beginning but the final point is not known until the complete shape is set up. That is made in theprivate Rectangle rect;
setStop
method. Further you see in
the Java API that a Rectangle
is
most easily constructed with x, y, width and height. And we would not like to do the mistake
of using negative values to width and height, don't we? The code is found beneath.How to answer the questions? Most easily we pass the question to
the rect
variable and then
return its answer. Have a look at this.
|
There is no problem declaring variables of the same data type at
the same line as done here, but I do not recommend it since you can not comment them if you like to, hence it
is not a good coding style. Anyway, as is done in the paintComponent
method we must avoid negative width and height values, hence the tests.
Further we create a somewhat bigger rectangle than the shape itself, only to be useful if it is a very tiny shape
hard to double click. From now on any PaintShape
recognizes
its area and remember it in a special variable.
Is it good to hold a variable such as this one? Doesn't it eat
a lot of memory? To the first question, it is mostly good, but the judge is you. And, yes it eats memory, not
much each shape but that is true. The opposite to use memory is to use CPU time, since if there is no Rectangle
to ask we have to make one
each time asked, passing the question to that temporarily constructed one. Hence each question will take
more time.
Of course this is half-truth!!! We could have built ourself that
valuable method contains
ourselves,
with no need for the Rectangle
.
But then we must consider the pros and cons with using a pre-built class' method. Or spending our time writing
the code ourselves. Both times it is about time--CPU or our time--versus eating memory. Admittedly the code is
not hard to write, thus I give it here, but the next time it might not be this easy.
This code is general code, not adapted to the
PaintShape
class, but that is easily done. To figure
out how it works, sketch a few points inside and outside a rectangle sketched on a squared paper. Remember that
ANDed clauses have to be true every one of them to return true, but OR is pleased with only one to be true.
Thepublic boolean contains(int Xother, int Yother, int w, int h) { return (Xother >= myX && Yother >= myY && Xother + w <= myX + myWidth && Yother + h <= myY + myHeight); }
PaintShape
class is done, with the Rectangle
or with the code above that of course is the most economic one. Still you
have to make yourself proper widths and heights.
MouseEvent
class. We know that any action stirs up an
event, a mouse action raises MouseEvent
.
The Java API says
"An event which indicates that a mouse action occurred in a component. This event is used both for mouse
events (click, enter, exit) and mouse motion events (moves and drags).
This low-level event is generated by a component object for:
The PaintPanel
class shall listen to mouse clicks, and it is prepared to do the task since
we use the MouseAdapter
from
earlier columns. In the MouseAdapter
class
there is a method mouseClicked
that
we haven't used so far, but now we add it within the addMouseListener
code block, as the other two are. A mouse click is a down-up within a short
time slice. But we are looking for a double mouse click, how do we do then?
|
There are two tests, the first one fetches the click count, understood
as the number of consecutive clicks considered as double clicks (that speed is adjustable at the Mouse object
in the OS/2 System folder (or whichever operating system you use)). If the click count is more than 1 click, we
consider it a double click. The next test is analogous to the other two event catchers, listen only to the chosen
button using a button mask.
If passing the test we continue with fetching the mouse coordinates
and we construct a java.awt.Point
out
of them, a convenience class holding x and y. That new point we pass to another method that we have to build.
What are the prerequisites of that method?
The method removeShape
is called with a Point
as parameter. The purpose is to find the shape held in
storedShapes
(the vector holding all the shapes) that
contains that Point
. Every
time we are thinking of how to find anything held in a vector, or an array for that matter, we have to think "a
for-loop" or at least "a while-loop". That is since we are to looking at each object held, from
the first one to the last, a job suitable for a loop.
Further remember that a Vector
does not think of which type of object is added to itself, everything is
considered of the class Object
.
(With the restriction that primitive data types can not be added, they have to be wrapped in their counterpart
classes respectively.) Since everything is considered an Object
we have to tell javac
that we know that there is only PaintShape
objects added, by casting the objects before we assign them to tempS
.
|
The for-loop will pick up every object stored in
storedShapes
, next we have to find out if the Point
is inside the rectangular area
of tempS
. If that test
receives a true
, tempS.contains(xy)
is
true
, we call the convenient method
removeElement(Object obj)
of the
Vector
class. And that is it. Only a call to repaint
so the canvas is to be repainted
as soon as Java finds it suitable.
Finally a break
statement since we do not need to continue the loop any longer. The break
is always breaking the innermost loop it is found inside. That loop only. The loop is of the common kinds, for-loop,
while-loop or the do/while-loop. If you forget the break
statement the loop will continue until the end of the vector or the array is found,
that is, you might use a lot of CPU time if the object looked for was found quickly but you continue the search.
A final word on the repaint
. Yes, sometimes it does not work! I do not know exactly why, it seems like
the call is lost or ignored. The result is that the shape you liked to remove is still there--until you do your
next move when it is properly erased from the canvas. It was removed from the vector as it should, but the canvas
was not updated. I have tried many tricks but to no benefit, and the dirty tricks should not be shown in a column
like this one. Anyone giving me an explanation?
Look out now, you are removing the first shape
found in the vector, that might be the wrong one if their rectangular areas overlap each other. The point double
clicked might be contained within two or more shapes. But that is another problem. If you like to you may add
a button to the TopButtonPanel
,
or elsewhere, that calls the removeAllElements
method
of the storedShape
(the Vector
class). That is easily done,
go ahead.
We added one class or another to our repertoire,
Point
and MouseEvent
(used in earlier installments). A few new methods were found and used. Finding
objects was discussed. And some small digressions are done. I now consider most of the
PaintBox
finished, we may come back in the future, but
now it will rest for a while.
Next time I will discuss data structures. If you read my view on
Java 2 and Java 2 SDK, version 1.3, you read that these versions added a plethora of such stores to Java. Unfortunately
Java 1.1.8 is not that well equipped, but we will do our best anyway.
![]() |
|
|