Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
4.0 Introduction
Objects created from a class are capable of behaving according to the methods lying
defined within that class. The question is – how to write codes for those methods?
Methods are written in the form of functions. That is why, methods are also called
functions. Then the next question comes -- what is a functional form? Those who are familiar with
algebraic functions already know the answer.
Output y
f(x)
x Input(s) Fig-4.1(a) A Functional block
So a function, to its users, can be regarded as a black box which is capable of returning
an output value [obtained according to the codes written inside] when its users feed some
input argument(s). All methods in a java class take this view of a functional form as shown in
fig-4.1 (b). Therefore, java’s methods are nothing but functions.
Next question – what are the advantages of having this functional form of a class-
method? The answer is –
i) to hide low-level inner code details from its users. External use of methods may be
allowed without exposing inner details;
ii) to reuse portion(s) of class codes, as and when necessary, by simply using the
method-name, and
iii) to divide a complex computational task into a collection of smaller methods so
that problem solving becomes easier, object-specific and modular.
All these aspects will be clear gradually as we go further into its details.
When a function is specified as private, a member of that class type only can use that
function.
Any member, even belonging to external classes can use a public function or method.
Protected is mainly concerned with the inherited class types. That is, only inherited class
members can access the protected functions.
When no access –specifier is mentioned, by default java takes that function as public
within its own package boundary. [A folder or directory containing a number of defined
classes forms a Package]. Detailed discussions about such packages will be made in
chapter-9.
<return-type> is concerned with the data type ( like int, double, char, boolean,
etc. ....) of the output produced by the function. It may so happen that a function is defined
to take some actions inside but not to return any output value. Even in that case, the return-
type should be marked as void.
When a function is defined to return some output, the body of the function must include the
statement -- return < output variable>;
Each function, except those of type void, actually returns a value of the specified
data type. That is the property of a function. A function can be classified according to its
internal activities.
Functions are mostly used to produce some computational output. Actions inside a
function may be like reading and displaying some data values; assigning or modifying some
existing values; computing and returning a result for further use, etc.
Out of all such actions, some operations like write or modify can disturb or change the value
of some already stored member-data. Therefore, write or update operations are to be treated
very carefully and unrestricted public access should not be allowed.
On the other hand, read or display operations are not destructive, because read operations
do not change data values. So no access restriction will be necessary for such operations.
Based on the operational side effects, functions can be classified as either pure
functions or impure functions.
A pure function, when invoked, does not cause any change in the state of an object,
that means there will be no change in the values of the object’s instance variables.
For example readData() or getData() functions can be treated as pure functions as
they do not change any existing data values.
}
}
If you run this program, you will get the output as shown below –
Please Note:
1) The states of the objects std1 and std2 remain unchanged in whatever way you run the
pure method display (int, char). There will be no change in the object’s state.
2) Carefully observe how the control if-else statements are used in the gradDiv(int)
method. Details about such control statements you will learn in chapter-6.
3) The class PureFunc has used three methods – gradDiv(int), display(int,char) and the
main() method.
Impure functions, also called modifier functions, are those that can cause a change
of state in the object. That means, values of the object’s instance variables get modified or
changed depending on the current state of the object on which the function operates. Such
functions can cause some unwanted side effects if not carefully controlled by the access-
modifier.
So more restrictions are to be imposed on the use of such impure functions. To impose
different categories of restrictions – java allows optional inclusion of modifier along with
the access-specifier while defining member functions or methods of a class.
A modifier can be one of – final, native, synchronized, transient, volatile. The
functionality of a final method can never be changed. Final modifier prevents overloading
[not allowing same function names with different arguments] of functions. Final modifier
also prevents inheritance that is creation of a sub-class from a pre-defined base class is not
allowed. For advanced java programmers, knowledge of other types of modifiers may be
necessary but for the beginners, those are unnecessary and have been kept out of scope of
this book.
String name;
int accNo;
double accBalance;
double withdrawVal;
If you run this program, you will see the output as shown below (picture 4.1)–
Picture 4.1
Also note that the function main () can include both the types of member functions –
pure or impure. Programmer must be very careful about defining impure functions so far as
access-specifier is concerned.
As mentioned earlier, functions are capable of accepting zero (i.e. no argument), one
or more argument variables to return either one or no output value. Input values are passed
as arguments to the formal parameters while calling a function or method. For example: -
Please note that the function cover of the class Area is defined to accept two argument
values — length and width. In AreaDemo class, the default Area () constructor is utilized to
create two area objects – area1 and area2, which can use the cover function by passing
appropriate argument values i.e. (15,10) and (25,15) respectively as shown in example-4.3.
A function prototype is the first line of a function definition which describes the
return type of the output and the number and type of arguments to be passed to call it along
with its name and access-specifier. In example-4.3 the prototype of the function cover () is
On the other hand, a function signature is concerned mainly with the numbers and
data types of the arguments to be passed during its invocation by calling function name.
The signature of function cover () of example-4.3 is simply cover (int, int). Therefore, a
function signature is concerned with the function-name and arguments only, whereas a
function prototype takes care of the full functional interface -- including the signature,
return type of the output, access-specifier, modifier, etc.
Like constructor overloading, a function overloading is very much allowed in java. That
means, in a java class more than one method can have the same name but they must have
separate signatures --- i. e. arguments with different data types and with different numbers of
them. Thus function overloading is made possible due to different function signatures. An
example here can make the conception clear.
int a;
double r;
public void show()
{
Nothing to show.
The value of a is = 25
The value of x * y is = 432
Sum of two numbers is = 21.0
In this example-4.4, the method show () is overloaded four times. The first one
takes no argument and displays “Nothing to show”. The second one takes one integer
parameter and displays that value. The third one accepts two integer parameters and
displays the product of those two. Finally the fourth one takes two double type parameters
and displays the sum of them. Four overloaded methods are performing different tasks
although they bear the same function name.
Whenever you define a class, a new special data type gets created for use in your
program. Different Objects of that user-defined data type can then be created and used.
Class type
variable
reference An object of the
OverLoad class
obj
type created
In Memory
In reality, the variable obj simply holds the memory address where the actual OverLoad
object exists. That object has links to four reference addresses for four over loaded
functions named show (...). During run-time those addresses are resolved by observing
the arguments passed along with the function call (example-4.4).
Any object created out of a class type can invoke any method(s) or function(s)
belonging to that class. So the object obj of OverLoad class type can invoke any one of
the show (..) functions as per argument matching. Four overloaded function – show (...) --
have been called (example-4.4), simply by passing appropriate arguments.
obj.show(); // no argument
obj.show(25); // with one int type argument
obj.show(12,36); // with two int type arguments
obj.show(7.6,13.4); // with two double type arguments
Therefore, we can say that the function invocation or call has a general form of –
While defining a function formal parameters are specified, but during invocation of that
function, argument values are to be passed.
Just take a note of the use of (.) dot-operator in-between the object-name and the
function-name.
Sometimes a function needs to refer to a particular object, which is allowed to invoke it.
The this keyword can be used for that purpose. This refers to an object currently being used.
This can also be used as a reference to an object’s instance variable that can have different
reference for different object being created out of the same class type.
class ThisDemo
{
// instance variables
int age;
double fare;
}
}
Picture 4.3 Outputs of example-4.5
In example-4.5, this has been used to refer to the currently active object – either
passenger or child. The use of this keyword becomes essential when instance variables of
multiple categories of objects try to access the same method or function.
The keyword this can be used to hide local variables inside a method having the
same name as that of the class’s instance variables. In fact, this refers directly to the object.
So it can be used to resolve any name space conflict that might occur between instance
variables and local variables.
In example-4.5, the class methods are coded with this keyword, but the main ()
method invokes them with the objects’ instance variables. This just returns reference to the
currently used object. Here, this refers first to the passenger object and then to the child
object according to the reference of the object being used.
A word of caution: Programmers must be careful in using local variables and formal
parameter names so that no hidings of instance variables can occur.
There are two ways of passing an argument to a function – call-by-value and call-by-
reference. In the first case, the value of an argument is directly copied into slot of the formal
parameter. So there will be no side effects due to such parameter passing.
4.9.1 Call-by-Value
When a simple primitive type data (like int, double, float, boolean, char, etc) is passed to
a method or function, call-by-value is used. The actual benefit of call-by-value is that call
does not put the value in the location where the original function resides, but the value
change occurs only inside a copy of that function. Thus original definition with any
argument values remain unaffected.
If you run this program, the following output will appear in the Terminal Window –
This shows that call-by-value does not cause any change in the values of x and y
used in the call.
4.9.2 Call-by-Reference
class TestRef {
int a,b;
TestRef (int i, int j) {
a = i;
b = j;
}
void method( TestRef objRef) {
objRef.a *= 3;
objRef.b += 10;
}
}
If you run this program, the Terminal window will show the following (picture 4.4) –
You have just observed that passing argument using call-by-reference gives rise to a
change in the parameter reference. Within the parameter slot -- a reference address
pointing to data is put and not the actual data value. This can cause the side effects.
If the data value in the pointed location gets changed, the value accessed by the reference
pointer reads the changed value, not the value stored earlier. Whenever any argument is
passed to an object, side effects are bound to occur because objects are bound by
references. Java programmers should always remain careful about such side effects.
4.10 Conclusions
In a function oriented language, like C, both data and functions have isolated existence
within a program. But in Java, functions or methods remain enclosed together with data
members within a class or object and only those functions are capable of manipulating any
inside data member. This feature hides the internal details of an object but allows external
class/objects to interact through function interface by passing messages. These interfacable
functions of a class can be of either pure type or impure type.
A pure function does not cause any change in the state of an object, which means that the
called function does not cause a change in the values of instance variables. So pure functions
can be safely declared as public.
The difference between function prototype and function signature has been explained with
examples.
Argument passing is another very important aspect of any function call. Argument(s) can be
passed using either call-by-value or call-by-reference technique.
Call-by-value has no side effect; but call-by-reference gives rise to side effects.
A programmer must keep this point in mind. Call-by-value can be used with simple primitive
data types, but call-by-reference is got to be used for complex data types like object(s).