|
Part 3 One way to allow the light to be switched both on and off is to provide two buttons - one for on and one for off. This is what we will do in Example3. Most of the source code for Example3 is the same as Example2. Here is the code for the Example3 constructor:
We employ a second button object with a different ActionCommand property (equal to the button's displayed text by default). Now our LightBox object listens to two buttons, both of which send an ActionEvent object but with different ActionCommand properties. Run Example3 to confirm that you can now switch the light on and off at will. But wouldn't it be nice if we could use just one button to toggle the light on and off! This is what we will do next. The first approach we will take is to write some code to achieve a toggling effect - click once for on, click again for off. We will put this in our new Example4 class. So this time class Example4 will be the ActionListener for the button; it will perform the toggling logic and then tell the LightBox to switch on or off as required. Here is the source code for class Example4:
Each time the button is clicked, method actionPerformed(ActionEvent) is called. The boolean (true or false) variable called 'on' is toggled to the opposite of its current state ('!' is the Java 'not' operator). We then call method setOn(boolean) in class LightBox2 (a slightly enhanced version of class LightBox). Class LightBox2 extends class LightBox and adds 'accessor' (get/is and set) methods for the color property (or 'attribute') - the field 'col' already defined in the parent class (or 'superclass') LightBox. Class LightBox2 also provides a new method - setOn(boolean) - for external objects to set its 'on' state. The constructor of LightBox2 calls super() which means the equivalent method in the superclass (the no-parameters constructor in this case). We do this because the constructor code is the same as in class LightBox. We could add some additional statements in our new constructor, but the call to super() must be the first line (if it is included). Notice that we do not need to specify the fields 'on' and 'col' in this child class beacuse they are already specified in the parent class. Similarly, we do not need to put in code for methods paint(Graphics) or Dimension getPreferredSize() because we inherit these from the parent class. However, we could reimplement ('overide') them here if we wished to change the way that they worked. Here is the source code for class LightBox2:
Another way to achieve our goal of having a light controlled by a single button would be by having a toggling light! This is what we will do for Example5. The first step is to create our toggling light class. We will call this class ToggleLightBox and base it on class LightBox2. This time the ActionListener will be the toggling light class, with the toggling action in the actionPerformed() method as before. Here is the source code for class ToggleLightBox:
Notice that there are two constructors in this class. The name is the same in each case but the parameters are different. The first has no parameters, and the second has one - class Color. This technique can be applied to ordinary methods too and is called 'method overloading' (same method name, different parameter types or number of parameters). In our case it provides a convenience. Without the second constructor, one might need to write the following code to get a cyan colored light object:
but by using the second constructor we can simply write:
Here is the source code for class Example5:
This example demonstrates a fundamental aspect of object-oriented programming - that you can create any number of objects from a class. There is another important lesson to learn here. Notice that the constructor is both long and repetitive. This is a sign that we should consider creating a submethod. By using a submethod (called addButtonLightPair(Color)), the code becomes much shorter - and also more likely to be free of errors and easier to maintain. Here is our revised class:
In a case like this, creating a private (not called from outside the class) submethod is an excellent solution. Whenever you find that you have code that performs basically the same functionality in a number of places, perhaps in different methods (or even different classes), consider creating a new method and calling it as required. If the new method is general in nature and could be useful again, put it in a different package so that it can be used by many projects. In the last section we develop a useful, reusable GUI component.
(c) Kinabaloo Software
|