The previous chapter described the factthat computing systems can be viewed as consisting of objects which cooperatewith each other in order to carry out a task by means of the mechanism ofmessage sending. Events in the outside world such as a user requesting someinformation from an applet or application will give rise to a series ofmessages interchanged between objects within that applet or application untilone or more objects send some data to the outside world.
The previous chapter was, of necessity,brief and introductory. The aim of this chapter is to look at objects in moredetail and, in particular, show how they are implemented in the Javaprogramming language. In order to understand this it is worth examining whathappens when a message is sent to an object. For example, let us assume that anobject obj has been sent a message mess:
obj.mess;
What happens is that the object receivesthe message and decodes it. The decoding consists of looking at a list of allthe messages that it can receive and then executing the code corresponding tothe message mess. The question that this poses is how does the object accessthis information? The answer is that objects in Java are defined by means of amechanism known as a class. A class is very much like a template whichdefines the stored data associated with an object and the program code which isexecuted when particular messages are received.
The outline architecture of a class isas shown below:
Class Name {
State
Method1
Method2
Method3
...
Methodn
}
The first line contains the Javalanguage statements which define the name of the class. The state contains statementswhich define the individual data items that make up an object and the lines labeledmethod1, method2 and so on contain the code corresponding to each particularmessage that is sent. We use the term method to describe the chunk ofcode that is executed when a message is sent. For example, if an object canreceive a message x then there will normally be code identified by x withinthe class definition; this code is executed when the message is received by theobject.
The state part of a class will containdata items which are important to the object defined by that class. Forexample, assume that we have written an applet which allows password access tosome stored data. In such a system there will be an object defined by a classUser. In order for users to be processed correctly by this applet there willneed to be some means whereby such users can be identified and their passwordsstored. The state for each user is hence defined by two items of data: apassword and some unique identification such as that given to users when theyare registered at their home computer. In this example where there are twoitems of data associated with each object, such items will be held in variablesknown as instance variables. Each user object within the applet willcontain
these two items of data.
It is worth lingering a little longerwith this example. In the applet user objects will be sent messages such as:
user1.getPassword();
daveUser.newPassword("klxxx");
daveUser.newId("Dave33");
rolandUser.changeId("Roland66");
rolandUser.changePassword("zlxxghj");
robUser.checkPassword("xxkoil99");
The first expression involves the objectidentified by user1 being sent the message getPassword(). The result of thiscommunication is that the password for the user is returned and could then beused within the applet. The second expression involves the object identified bydaveUser being sent the message newPassword("klxxx"). Thiscommunication involves the instance variable corresponding to the passwordbeing given a value ("klxxx"). The third expression involves theobject identified by daveUser being sent the message newId("Dave33").This results in the instance variable corresponding to the identity of the userbeing updated to the string value "Dave33". The fourth expressioninvolves the sending of the message changeId("Roland66") torolandUser. This would result in the instance variable which holds the user’sidentity being changed. Similarly the fifth expression would involve theinstance variables representing the password of the user rolandUser beingchanged to a new value ("zlxxghj"). The final Java expressioninvolves the message checkPassword("xxkoil99") being sent to the useridentified by robUser. This results in a check being made that robUser has thepassword value "xxkoil99" in the instance variable which holds thecurrent password of the user.
An important point to make about themessages above is that two pairs of messages look very similar; for example,newPassword and changePassword seem to do the same things. What we have assumedhere is that they correspond to slightly different processing. For example, themessage corresponding to newPassword might access another instance variablewhich contains data that describes the date on which the user was first allowedaccess. This instance variable would not be accessed by changePassword. If theprocessing required by these two methods and the methods changeId and newIdwere the same, then they could, of course, be replaced by just one message
.
A class template for users that alsohave associated with them the date of last access would look something likethis:
Class User{
// Declarations of variables for thepassword of a user,
// the identity and the date of firstaccess
// Code defining the method getPassword
// Code defining the method newPassword
// Code defining the method newId
// Code defining the method changeId
// Code defining the methodchangePassword
// Code defining the methodcheckPassword
...
// Code for other methods
...
}
The symbols // introduce a comment on asingle line. Once you have defined such a class within a Java applet orapplication new users can be defined and space allocated for them. The code:
User rolandUser, daveUser, janeUser;
defines three user variables which willidentify User objects. Each of these users will eventually contain thevariables which hold their password, their user identity and the date theyfirst accessed the applet.
The statement above just informs theJava system that the variables rolandUser, daveUser and janeUser will be Uservariables. To allocate space requires a facility known as the new facility. Forexample, to allocate memory space for the object identified by rolandUser youwill need to write:
rolandUser = new User();
In order to reinforce the ideas justpresented let us take another example from a Java application. Let us assumethat we have written an applet which allows users to interrogate the prices ofshares on a stock exchange. We shall assume that the user of such an appletcarries out functions such as finding the current price of a share and alsoexamining the price of the shares as far back in the past as 365 days. Thismeans that we will need an object which we shall call ShareHistory. Thiscontains the last 365 days of prices for each share taken at the end of thedealing day.
The template for this object will looklike:
Class ShareHistory {
// Instance variable holding the last365 prices for
// each of the shares listed on thestock exchange
// Method code for findCurrentPrice
// Method code for findAnyPrice
// Method code for updatePrice
}
The first method, findCurrentPrice, willfind the price of a particular share which is the last one posted – normallythe price for the previous day’s close of business. The second method,findAnyPrice, given a day within 365 days of the current day, will deliver theprice of a particular share on that day. The third method will update the priceof a share at the end of a day’s trading.
Such an applet can deal with a number ofstock exchanges which in Java can be declared as:
ShareHistory tokyo, london, newYork;
with typical Java expressions being:
tokyo.findCurrentPrice("Daiwa");
london.findCurrentPrice("UNISYS");
newYork.findAnyPrice("IBM","22/09/95");
newYork.updatePrice("GeneralMotors", 333);
The first message to the receiver objecttokyo results in the current stock price of the Daiwa company being returned,the second message sent to the object london results in the current price ofthe computer company UNISYS being returned, the third message sent to the NewYork exchange results in the price of the stock for IBM on 22 September beingreturned. Finally, the fourth line updates the price of General Motors on theNew York stock exchange.
The two examples above are structurallysimilar. As you proceed through the book you will find that all classes willfollow this pattern of class definition, definition of variables and definitionof methods.
What are the reasons for defining datain such a way? Later in this chapter you will see how some of the more advancedfacilities related to objects lead to a high degree of reuse. Apart from reusethere is also the advantage of maintainability.
Software systems are subject to majorchanges in their lifetime. Recent surveys have suggested that as much as 80% ofthe development effort expended by a software company is devoted to modifying existingsystems. When you define objects using classes one of the things that you cando is to ensure that no user can use the instance variables of an object: thatall access to the information stored in an object is via methods. Thisprinciple is known as information hiding: the user of an object does nothappen to know the details of how that object is implemented. This means thatwhen a developer wants to change the implementation of an object, for exampleto speed up access to the object, then the instance variables and code of allthe methods change but the interface to the object – the method names andarguments themselves – do not change. For example, after using the stockexchange system detailed above for a number of months the developer maydiscover that there is a particular pattern of access to objects, for examplehe or she may discover that most of the access is to recent data, and that anew way of storing the stock prices which takes advantage of this access leadsto an enhanced run-time performance. This new way of storing the price datawould inevitably lead to large changes in the code of the methods that thestock exchange object recognized. However, it would not lead to any changes inthe format of the messages. For example, users could still send messages suchas:
tokyo.findCurrentPrice("Daiwa");
london.findCurrentPrice("UNISYS");
newYork.findAnyPrice("IBM","22/09/95");
newYork.updatePrice("GeneralMotors", 333);
as before, without any changes beingmade to the applet. This means that any applet or Java application which usesthe stock exchange class does not need to be changed.
Some concepts
Almost certainly the next question thatyou are asking yourself is: what is the detailed syntax of a class in Java?This question will be answered fully in Chapter 5. At this stage in the book wewould like to give you an idea of how you write such classes. An example of asimple Java class is shown below. It is simple, and hence unrealistic; however,we have included it for teaching reasons: we do not want to get the detail ofclasses in the way of understanding what, for many, is regarded as a difficultconcept.
A robot
The class below is taken from a screenrobot applet. Here the user can direct a robot to move on a twodimensional board,where the coordinates of the board are expressed as x and y coordinates.When the robot is moved the screen updates itself by showing the next position.The lowest x and y positions are 1 and the highest x and ypositions are 8. An example of this board and the current position of a robotis shown in Figure 3.1.
Let us assume that we need a number ofmessages to be sent to the robot which can send the robot vertically upwards(to the north), vertically downwards (to the south), horizontally leftwards (tothe west) and horizontally rightwards (to the east). We also want to be able tosend messages to the robot to send it upwards and to the right, upwards and tothe left, downwards and to the left and downwards and to the right.
Examples of these messages are shownbelow:
newRobot.up();
oldRobot.down();
newRobotleft();
oldRobot.right();
oddRobot.leftUp();
oddRobot.rightUp();
smallRobot.leftDown();
smallRobot.rightDown();
Robot newRobot, oldRobot, oddRobot,smallRobot;
In the discussion that follows we shallassume that there is no possibility that the robot will travel beyond theconfines of the square grid. This would normally be achieved by means ofmessages which would be sent to a robot to check that it is not on the edge ofthe grid.
The first part of the Java classdefinition for a robot is shown below:
Class Robot {
int x, y;
This states that the class is known asRobot and that there will be two instance variables x and y which define wherethe robot is on the grid; these variables will hold integer values. Thedefinition of the up, down, right and left messages is shown below:
public void up() {
y++;
}
public void down() {
y--;
}
public void right() {
x++;
}
public void left() {
x--;
}
Each of the method definitions startswith the keyword public. This specifies that the method can be used by otherobjects and by code written outside the class. The keyword void states that novalue is to be returned by the method; this keyword is followed by the name ofthe method and a list of its arguments; in the case of the four methods abovethere are no arguments. The first method up moves the robot one grid upwardsand the code following the first curly bracket does this. For those of you whohave programmed in C or C++ you will recognize the statement y++ as the codewhich increments the value of the instance variable y by one. This isequivalent to a statement such as y:= y + 1 in a programming language such asPascal.
The code for the down message is similarexcept that it decrements the instance variable y by one, hence moving therobot downwards. The code for right and left is similar apart from the factthat it accesses the x instance variable.
The code for the other methods is shownbelow:
public void upRight() {
y++;
x++;
}
public void downRight() {
y--;
x++;
}
public void upLeft() {
y++;
x--;
}
public void downLeft() {
x--;
y--;
}
The code for these methods isself-explanatory.
Let us assume that as well as methodswhich move the robot we require methods which find out the position of therobot, for example to discover whether the robot is in a position where it ispossible to move. Assume that the two methods we need will be called findxPosand findyPos. When a message corresponding to findxPos is sent to a receiverobject what is returned is the x position of the object and when a findyPosmessage is sent to a receiver object what is returned is the y position of theobject. The code for these two methods is shown below:
public int findxPos() {
return (x);
}
public int findyPos() {
return (y);
}
There are a number of things to noticeabout this code. First, the two methods are declared as public; this means thatthey can be accessed by other methods and by code outside the class whichdefines robots. The second thing to notice is that the keyword int is usedinstead of the previously used void. This means that the method will returnwith an integer value. The final thing to notice about the code is that in thebody of the method, between the curly brackets, the keyword return is used.This means that the value specified by the return is the one that is returnedby the method. In the case of the findxPos method this is the value of the xinstance variable.
So far we have described methods withoutarguments. The next collection of methods show how arguments can be used. Thefirst method checkAtPoint checks whether a robot is at a specific point on thegrid. The second method moveToPoint moves a robot from its current point to anew point specified by two arguments. The code for these two methods is shownbelow:
public boolean checkAtPoint(int xPos,yPos) {
return (x==xPos && y==yPos);
}
public void moveToPoint(int xPos, yPos){
x = xPos;
y = yPos;
}
The first method is headed with theboolean keyword. This means that it will return a value which is either true orfalse. The two arguments to the method are xPos and yPos which represent apossible position of the robot. The body of the method returns true if the xinstance variable contains the same integer as the xPos argument and the yinstance variable contains the same value as the yPos argument. Again those ofyou who have programmed in C and C++ will realize that Java has similarfacilities to those found in these languages. The == symbol stands forarithmetic equality while the operator && stands for Boolean and
Thus, when the Java interpreter executesthe code shown below:
strangeRobot.checkAtPoint(3,4);
it checks whether the receiver objectstrangeRobot is at the point (3, 4). What happens is that the interpreter firstrecognizes strangeRobot as of class Robot. This will be because it will havebeen defined previously in the Java program which uses the code as, say:
Robot strangeRobot;.
The interpreter will look for a methodcorresponding to the name checkAtPoint. It will find the method and execute thecode. However, before executing the code it will copy the values 3 and 4 to thearguments xPos and yPos. It will thus evaluate the expression:
x==3 && y==4
and will return either true or falsedepending on whether the receiver object is at the position which is defined bythe contents of its instance variables.
The code for the method movePointreturns no value since it is headed by the keyword void. It has two argumentsxPos and yPos which are the new points to which it is to be sent. The codewithin the body of the method updates the two instance variables with thevalues given by the arguments.
So far in this section we have describedmethods which access the state (instance variables) of an object and whichupdate those variables. There is, however, one class of method which we haveomitted: methods which create an object. There are a number of ways of creatingan object. We have said very little about how objects are created apart fromthe fact that the new facility is used, for example the declaration:
Robot fredRobot = new Robot();
declares a variable fredRobot, allocatesspace for a Robot object and identifies this space as fredRobot.
The one problem with this form ofdeclaration and allocation of space is that the instance variables of theobjects declared in such a way are uninitialized. Java contains a facilitywhereby an object can be given a value when it is declared as above. In orderto do this all that is required is to declare a new method within the classtemplate which has the same name as the class. So, for example, in our Robot classwe would need to define Robot as:
Robot() {
x = 1;
y = 1;
}
The effect of this is that whenever youdeclare a Robot object, for example in:
Robot slowRobot = new Robot();
the Java interpreter will first examinethe methods defined in Robot looking for a method which has the same name asthe class name. If it does not find such a method, then it will just create anobject which has uninitialized instance variables. However, if it discovers amethod with the same name, then the code for the method is executed. In thecase of the code shown above this will create a robot which is initiallypositioned on the bottom left square of the grid. The method, known as Robot,is called a constructor. Constructors can have specified defaults such as Robotshown above where the default is that a newly created robot object is placed onthe square (1,1). However, constructors can also be associated with argumentswhich represent a user’s specified initial value. An example of a Robotconstructor which sets the x position and y position of a robottaken from values supplied by the programmer is shown below:
Robot(int xPos, yPos) {
x = xPos;
y = yPos;
}
An example of its use with the newfacility is shown below:
Robot denseRobot = new Robot(6, 5);
This line of code declares an objectdenseRobot which is created by applying new to the Robot method. This methodrequires two arguments (in the example above these are 6 and 5) which are usedto update the x and y instance variables within denseRobot.
Messages and classes
It is worth recapping the mechanismsused within Java for sending messages and what happens to these messages. Whenthe Java interpreter encounters an expression such as:
receiverObject.message(arguments);
it will first determine which class thedestination object is defined by. To do this it will scan all the declarationswithin the code of the applet or Java application. If it finds the name of theobject within a declaration then it recovers the name of the class whichdescribes it. It will then scan the code of the methods associated with thisclass. If it finds a method with the same name as the message string then thecode is executed; if not an error is flagged. If the message is associated withany arguments these are copied through as the arguments of the method and thecode associated with the method is executed. This is a slight simplification asyou will see later in this chapter. However, in essence, it represents theprocessing cycle that occurs.
Inheritance
So far we have outlined a number ofpowerful facilities contained in the Java programming language which are usedto construct objects and define the methods which correspond to the messagesthat Java objects receive. This section introduces what is certainly the mostpowerful facility within Java: that of inheritance. In order to introduce theidea we will first describe three increasingly complex examples of whereinheritance is useful. The first example will introduce the idea of inheritancein an abstract way. Later chapters of the book show how inheritance is usedwithin more realistic applets and applications.
The augmented set
The first example concerns a set wherewe need methods which find out the size of the set and add integers to the set,together with an operation which finds the sum of the elements in the set. Onevery efficient way of implementing such a set in such a way that summation isnot too inefficient an operation is to have a class which has two instancevariables: intSet, the set of integers, and an integer sum which contains thecurrent sum of the integers. This is an efficient implementation because anymethod which needs to find the sum only needs to look it up in the variable sumrather than iterating through intSet.
An example of an object described bythis class is shown in Figure 3.2. Here the instance variable sum contains thecurrent sum of the integers in the instance variable intSet. Let us assume thatwe have already implemented a set of integers described by the class intSetshown below, where the code for each of the classes is not shown and where wehave just listed the instance variables without defining their types. The classdoes not require a summation method and hence does not require an instance variableto contain a sum.
Class IntSet {
int intSetvar[];
public boolean includes(int no) {
...
}
public int size(int no) {
...
}
public void add (int no) {
...
}
public void remove(int no) {
...
}
}
Let us assume that this set has beenimplemented for another project and is associated with the four methods shownabove which check that a particular number is in the set, find the size of theset, add an element to the set and removes an element from the set.
Now let us assume that we need a set towhich we wish to send messages that calculate its sum. We are faced with onechoice immediately: we can program a new class from scratch. However, another choiceis to use a facility known as inheritance which takes advantage of the setclass we have just written. Before seeing it in action it is worth providingsome definitions.
Inheritance is arelationship between two classes: if a class A inherits from a class B,then class A, as well as being able to use all of its own instancevariables and methods, can use all the methods that B can use and canalso use any instance variables that B can use. As an example of thisconsider the two classes X and Y below without the code for their methods.
Class X {
// Declarations for u v and w
// Code for method A
// Code for method B
// Code for method C
}
Class Y {
// Declarations for l and m
// Code for method R
// Code for method S
// Code for method T
}
If class Y inherits from class X, then,firstly, all the methods in class Y can refer to not only the instance variablesin class Y but also the instance variables in class X; and secondly an objectdescribed by class Y can have messages corresponding not only to the methods R,S and T but also the methods A, B and C.
Classes can inherit from classes whichinherit from other classes. As an example consider the three classes shownbelow:
Class X {
// Declarations for u v and w
// Code for method A
// Code for method B
// Code for method C
}
Class Y {
// Declarations of l and m
// Code for method R
// Code for method S
// Code for method T
}
Class Z {
// Declarations of n and o
// Code for method G
// Code for method H
// Code for method I
}
The same holds for the instancevariables: methods in class Z can refer to not only the instance variables nand o defined in Z, but also the instance variables l and m which it inheritsfrom Y and also the instance variables u, v and w which Y inherits. We canrepresent this relationship graphically as shown in Figure 3.3.
This diagram, which shows that class Zinherits from class Y which, in turn, inherits from class X, is known as a classhierarchy diagram. Class hierarchies are a very powerful way of describingthe relationship between classes. This relationship lies at the heart of theuse of an object-oriented programming language as a medium for software reuse. Considerthe classes described below where B inherits from A:
Class A {
// Declarations of a b and c
// Code for method J
// Code for method K
// Code for method L
}
Class B {
// Declarations of e f g and h
// Code for method X
// Code for method Y
X
Y
Z
// Code for method Z
}
Also consider the statements:
• An object of class B can be sent amessage associated with method K.
• An object of class A can be sent amessage associated with method B.
• Method Z in class B can refer to theinstance variable a.
• Method Y in class B can refer to theinstance variable e.
• Method K in class A can refer to theinstance variable g.
Which of these statements are true?
The first is true since A contains amethod K which B inherits. The second is false since there is no method calledB, only a class called B. The third is true since there is an instance variablea in A which is inherited by B. The fourth is true since the instance variablee is defined in the class B. The final statement is false; class A does notinherit from class B, but vice versa.
There is only one further rule thatneeds to be explained about inheritance before we return to the example thatstarted this section. This concerns classes which contain methods that have thesame name as methods in the class which they inherit. Consider the classesshown below, where class B inherits from class A.
Class A {
// Declarations a b and c
// Code for method J
// Code for method K
// Code for method L
}
Class B {
// Declarations e f g and h
// Code for method X
// Code for method K
// Code for method Z
}
If a message with the name K was sent toan object of class B which method would be executed?
The answer is that it would be themethod in class B. The general rule is that whenever a class inherits fromanother class and there is duplication of method names between the class andthe one it inherits from, then the method from the class that inherits is theone invoked. Consider the classes shown below:
Class D {
// Declarations of a b and c
// Code for method J
// Code for method K
// Code for method L
}
Class E {
// Declarations of e f g h i and j
// Code for method J
// Code for method K
// Code for method Z
}
The following statements are true:
• When a message is sent to an objectdescribed by class E and the message uses the selector J, then the method Jdefined in E is invoked.
• When a message is sent to an objectdescribed by class E and the message uses the selector Z, then the method Zdefined in E is invoked.
• When a message is sent to an objectdefined by class E and the message uses the selector L, then the method Ldefined in class D is invoked. However, the following statement is not true:
• When a message is sent to an objectdefined by class D and the message uses the selector K, then the method Kdefined in E is invoked.
Because D does not inherit from E, themethod corresponding to K defined in D is invoked. This rule about similarnames for methods holds whatever the level of the inheritance hierarchy. Forexample, consider the three classes shown below:
Class A {
// Declaration of r and s
// Code for method J
// Code for method K
// Code for method L
}
Class B {
// Declarations of e f and g
// Code for method J
// Code for method U
// Code for method V
}
Class C {
// Declarations of l m n and o
// Code for method U
// Code for method R
// Code for method S
}
If class C inherits from class B which,in turn, inherits from class A, then when a message involving the selector U issent to an object defined by C, the method U defined in C is invoked; when amessage using the selector J is sent to the same type of object, the method Jdefined in class B is invoked. Before returning to the summable set example itis worth defining a concept that you will meet a number of times later in thebook. The protocol of a class is the list of messages that can be sentto an object defined by that class. The protocol will contain those methodnames defined within the class, together with the methods from those classes itinherits from. For example, the protocol of the class C defined above containsthe messages corresponding to the methods U, R, S, J, V, K, L. It is now worthcontinuing with the summable set example. You will remember that we had alreadydefined a set of integers as:
Class IntSet {
int intSetvar[];
public boolean includes(int no) {
...
}
public int size(int no) {
...
}
public void add(int no) {
...
}
public void remove(int no) {
...
}
}
and that we wanted to define a new classwhich provided all the facilities of IntSet but also provided a method whichsummed the integers within the set.
You will remember that the way to dothis is to somehow define a new class which has an instance variable whichholds the current sum of the values and an inherited instance variable whichholds the members of the set. We can easily define this new set by writing downits name, specifying the names of the instance variables and then writing codefor the five methods. However, inheritance allows us to save some time, sinceby using inheritance we can reuse some of the elements of IntSet. We shallassume that the new class which describes summable sets is called SummableSet.The code skeleton describing its structure is shown below:
Class SummableSet {
int sum;
public int totalSum() {
...
}
}
Here a new method totalSum is definedwhich returns with the sum of the set; also defined is an instance variable sumwhich holds the current sum of the set.
In Java if we wish to specify that a setinherits from another set then we write this using the keyword extends. Thefull definition of SummableSet is then:
Class SummableSet extends IntSet {
int sum;
public int totalSum() {
...
}
}
This states that we have defined a newclass called SummableSet which inherits the instance variables and the methodsfrom the existing class IntSet. If this class inherits from IntSet, then anobject described by SummableSet can be sent messages corresponding to themethods includes, size, add and remove. There seems to be no reason why wecannot now write code such as:
SummableSet sms;
sms = new SummableSet();
sms.add(23);
where the semicolon is used as with mostC-like programming languages to terminate individual Java statements.
Unfortunately, there is a problem: thecode for the methods add and remove is incorrect. The code for add and removewould correctly alter the set of integers by adding and removing items from it;however, they do not affect the current sum. For example, there may be threeintegers in the summable set which are 45, 3, 10 with the instance variable sumholding 58 which is the sum. If add is invoked with the argument 20, then 20would be deposited in the set but the sum would remain at 58. What we need arenew versions of add and remove.
These need to be embedded in the classSummableSet, making its code skeleton look like:
Class SummableSet extends IntSet {
int sum;
public int totalSum() {
...
}
public void add(int no) {
...
}
public void remove (int no) {
...
}
}
The code for the method add would add noto the set and also add the value of no to the instance variable
sum. The code for the method removewould remove no from the set and subtract its value from
the instance variable sum. Perhaps wecould then expect the code for add to look something like:
public void add(int no) {
add(no);
sum = sum + no;
...
}
where the first line introduces themethod, the second line uses the method add declared in the class
IntSet to carry out the insertion of nointo SummableSet and the third line adjusts the instance variable
sum so that it is up to date andcontains the current sum. We might also expect the code for remove
within SummableSet to look like:
public void remove(int no) {
remove(no);
sum = sum - no;
...
}
There is one problem, however. Whichversion of add does the first extract refer to: the one defined in IntSet orthe one defined in SummableSet? Similarly which version of remove does thesecond extract refer to: the one defined in IntSet or the one defined inSummableSet? Well, the rule that we have given previously states that when amethod M is invoked associated with a class C, then method M issearched for in C, and if it is there then it is invoked; if it isn’tthere then the search continues in the next class that it inherits from, namelythe class in the next level in the inheritance hierarchy. This means that, forexample, inside the method add defined in SummableSet there is a call toitself. When this is invoked there would be another call to itself, and so on.This means that the method could be in a continuous loop and never exit. Thesame would, of course, be true of remove.
The way to get over this is to use adevice which slightly overrides the way in which methods are searched for whenthey are invoked. This involves the use of a dot notation. In order to refer tothe method in the class that SummableSet inherits we refer to it as super.add.
In order to see how this works, examinethe code shown below for the correct version of add within SummableSet:
public void add(int no) {
intSetvar.super.add(no);
sum = sum + no;
...
}
This instructs the Java interpreter tostart its search for a method to execute not within the class which describesthe object SummableSet, but within the class IntSet (the keyword superinstructs the Java system to look at the class above). The code for removewould be similar:
public void remove(int no) {
intSetvar.super.remove(no);
sum = sum - no;
...
}
It is worth recapping the points thatthe example and supporting text has illustrated. First, it has shown howinheritance works. Second, it has illustrated reuse to a certain extent: thereuse of IntSet was not massive since we had to redefine the methods add andremove within SummableSet, but nevertheless some reuse was employed. Finally,the text described the way in which the Java system looked for methods toexecute: by traversing the inheritance hierarchy, normally starting with theclass that was defined by the object which is being sent a message, but withthe use of the dot notation facility overriding this starting point.
Tidak ada komentar:
Posting Komentar