Академический Документы
Профессиональный Документы
Культура Документы
Module 1
Class Design
Objectives :
Upon completion of this module, you should be able to :
This module describes the object-oriented paradigm and the object-oriented features of
the Java programming language.
CETTM,MTNL,Mumbai
I 683
1 PA
Subclassing
Object Oriented Programming provides for inheritance. The use of inheritance is to
create specialized classes. The specialized classes derived from the parent class (super classgeneral class) are called sub-classes or child classes.
In case of inheritance of living things the offspring is a specialized one which takes some
characters from father and some from mother. This type of inheritance from more than one
parent is called multiple inheritance. The main goal of inheritance is evolution. Evolution means
creating more specialized one or more customized one.
Many languages provide for the multiple inheritance in sub class formation. If sub class
is not properly defined then this type of inheritance creates conflicts between inherited
Properties. In living things the inheritance of same property is controlled by the differentiation of
recessive and dominant genes. The property of the dominant gene is expressed in the offspring.
As there is no such provision in computer languages, the common properties of the parent
classes are to be controlled by the programmer. This puts a lot of restriction and some times the
process is disastrous while programming. Hence Java does not provide for multiple inheritance.
The multiple inheritance provides for incorporating the properties of different classes in one sub
class which is very useful many times. Hence, in Java this feature is also retained with the use
of interfaces. This will be dealt with afterwards.
In Java, a subclass can be descended from only one parent class. Hence Java only
supports single inheritance. But there is no restriction in creating many subclasses from a single
parent class. Whenever a subclass is created from a parent class then all the properties of that
parent class will be automatically assigned to the subclass.
Code reusability is a key advantage of object-oriented languages over non-objectoriented languages. Inheritance is the mechanism by which this is achieved. An object (of
subclass) can inherit the variables and methods of parent object (super class). Sub class can
keep those methods and variables which it wants, and replace those which it doesn't want.
Hence in the sub class the programmer need not write any code for the parent properties for
which code is written in the parent class.
Defining a subclass
The key word extends is used to define a sub class. The keyword should be followed by
the name of the super class of which the sub class is being extended. The immediate subclass
is called direct subclass and the immediate super class is called direct super class. The
hierarchy of classes can go from subclass to subclass. All the sub classes in the hierarchy
downwards retain the properties acquired or incorporated by all the super classes. It means that
if a subclass C is extended from a class B and the class B itself is a subclass of A then class C
has all the properties (methods and variables) of class B and class A.
Ex :
class A
{
statements
}
class B extends A
{
statements
// This class has all the properties(methods and variables) of class A
// This class has also created properties of its own due to the statements
written in it.
}
class C extends B
{
statements
// This class has all the properties(methods and variables) of class A and
B
// This class has also created properties of its own due to the statements
written in it.
}
The Object class is the super most class in Java. Hence the class Object cannot have
the extends clause in its class definition. All other classes in Java are either direct subclasses of
Object class or subsequent subclasses. If any class does not contain extends clause in its
class definition then that class must be a direct subclass of the class Object.
For example, let us have the SavingsAccount class so that it has attributes
accountNumber, accountName, address, drawingPower and minimumBalance.
Ex. : Refer Program 1.1
Now suppose we also need a class CurrentAccount. A CurrentAccount also should
have attributes accountNumber, accountName, address, drawingPower and overDraft and
many other properties we can represent with fields.
Ex. : Refer Program 1.2
If we keenly see these two classes then it is evident that many features (methods and
fields) are overlapping. In this way, suppose we have to create many different types of accounts
then many features which are common to each account are to be repeated in each class.
Suppose that it is possible to keep all the common features in one class and those can be used
in other classes without rewriting them. Then we need to write only specialized features in other
classes and common features can be inherited from the class where those features are written.
As there is no limit to this reusability we can save lot of resources and coding efforts. This
reusability feature is incorporated in inheritance.
Based on this let us create a super class named Customer which contains all the
common features of the accounts. Then we will create different classes of accounts customized
in some way. For that we create two classes for Savings Account and Current Account with
inherited properties from Customer.
Ex. : Refer Program 1.3 (Customer class)
Ex. : Refer Program 1.4 (SubclassSavingsAccount class)
Ex. : Refer Program 1.5 (SubclassCurrentAccount class)
In the above examples we have created two subclasses of Customer. Both the classes
created are direct subclasses of Customer class. There is nothing to stop us from going further.
We can define subclasses of SubclassSavingsAccount for Savings Account with passbook
and more. For example, we create one SavingsAccountPassbook class for the issue of pass
books. Here change is only for pass books.
This SavingsAccountPassbook class not only inherits from its immediate superclass,
SubclassSavingsAccount, but also from SubclassSavingsAccount's superclass,
Customer. Thus the SavingsAccountPassbook class has also an account Number, Name of
the account holder, address of the account holder, account holders drawing power and so on.
This is called multilevel inheritance. There's no limit to this chain of inheritance, though getting
more than four or five classes deep makes code excessively complex.
Ex. : Refer Program 1.6
Access Control
CETTM,MTNL,Mumbai
I 683
3 PA
While programming, if the programmer gives access to all the variables and methods he
uses, then it may cause bugs or corruption. Some unknown function can change the value of a
variable when the programmer does not expect it to change. This plays all sorts of havoc.
Most OOP languages including Java allow you to protect variables from external
modification. This allows you to guarantee that our class remains consistent. For example, in the
Customer class we'd like to make sure that no block of code from some other class is allowed
to make the drawingPower greater than the assigned value while constructing the object.
Therefore we want a way to make the following illegal from other classes.
sb.drawingPower = 10000.0;
If the above code works then it means that a sb object is made with drawingPower of
Rs. 5000.0 but subsequently that sb is made to operate with drawingPower Rs. 10000.0. Thus
the whole idea of making a consistent Customer class fails.
Therefore the variable drawingPower should not be changeable from outside the class.
If the variable drawingPower is not approachable (accessible) from outside the class then its
value can not be changed. This type of access restrictions are to be imposed on methods and
variables to keep the program consistent. The different types of access permission may be
required for giving access to different persons. Based on this principle Java provides four types
of access modifiers. The Java methods and variables can be at one of the four access levels ie.
public, private, protected or unspecified (default). The Java classes can be either at public
level or at default level.
Modifier
private
default
protected
public
Same Class
Yes
Yes
Yes
Yes
Accessibility Criteria
Same Package Subclass
Universe
Yes
Yes
Yes
Yes
Yes
Yes
Hence a variable or a method marked private is accessible from the same class only.
The variable or the method which does not have any access modifier means it is at default
access modifier level. Such variable or method is accessible within all the classes of a package.
Hence default modifier is also called package friendly access modifier.
The access modifier protected is friendlier than default modifier. It allows the methods
and variables to be accessible from within all the classes of the package and from the
subclasses residing in the other packages also.
Hence while using the access modifiers, first it is to be decided that how far the method
or the variable is required to be seen for handling and accordingly appropriate access modifier is
to be used.
Ex. : Refer Programs 1.7.1, 1.7.2, 1.7.3, 1.7.4 and 1.7.5
Overriding Methods
In addition to producing a new class based on an old one by adding additional features,
you can modify existing behavior of the parent class.
If a method is defined in a subclass so that the name, return type, and argument list
match exactly those of a method in the parent class, then the new method is said to override the
old one.
In J2SE version 5.0, these matching rules have changed slightly. The return type of the
overriding method can now be a subtype of the return type in inherited method.
Over riding is restricted to visible methods of super class. Method of the super class with
default access modifier is not visible in the subclass residing in another package and hence
cannot be overridden. Similarly final, static or private methods of the super class cannot be
overridden.
Suppose that one day you've just finished your Balance class. It's been plugged into your
banking transactions which is doing merrily transacting customers business. Then your pointy
haired boss rolls in the door, and tells you that he needs the Balance class to keep minimum
balance Rs. 10000.0 instead of Rs. 5000.0.
What are you going to do? Your first reaction may be to change the class that you
already wrote so that it enhances the minimum balance. However you're using that class
elsewhere and things will break if you change it.
You could create a completely new class in a different file, either by starting from scratch
or by copying and pasting. This would work, but it would mean that if you found a bug in the
Balance class now you'd have to fix it in two files. And if you wanted to add new methods to the
Balance class, you'd have to add them in two files. Still this is the best you could do if you were
writing in C or some other traditional language.
The object oriented solution to this problem is to define a new class, call it
ModifiedBalance, which inherits from Balance class and imposes the additional constraint that
a minimum balance may not go below Rs. 10000.0.
To do this you'll need to adjust the place that minimumBalance can be changed, the
withdraw() method. Hence the withdraw() method must be overridden. This means the
subclass has a method with the same signature as the method in the superclass.
The first thing to note about this class is what it doesn't have, balance field. This is
provided by the superclass Balance. Nothing about fields (or methods which is not overridden)
has changed so they don't need to be repeated here.
Next look at the withdraw() method. This is different than the withdraw() method in
Balance. It imposes the additional constraint.
Ex. : Refer Programs 1.8.1, 1.8.2, 1.8.3 and 1.8.4
CETTM,MTNL,Mumbai
I 683
5 PA
Secretaries could be given read-only access. Therefore the secretary class would have
additional methods to read data that aren't part of the super class.
Data entry clerks might be allowed to read the database and to create new records but
not to modify old records. Therefore the data entry class would inherit from the secretary class
and have methods to allow adding new records. A supervisor class would inherit from the data
entry class and also have methods that allow modification of existing records. Finally a database
manager would inherit from supervisor, but have new methods that allowed database managers
to change the structure of the database.
As a practical example, recall that the SavingsAccount added a minimumBalance
field and a minimumBalanceGetter() method that the Customer class didn't have.
Ex. : Refer Program 1.4
Polymorphism
SubclassSavingsAccount is a subclass of Customer. SavingsAccountPassbook is a
subclass of SubclassSavingsAccount and Polymorphism is a subclass of
SavingsAccountPassbook. Polymorphism class implements the interface MyInterface. If you
instantiate Polymorphism with new, you can assign that object to any of the variables of type
Polymorphism or SavingsAccountPassbook or SubclassSavingsAccount or Customer or
MyInterface. As Object class is the super class for all the classes of JAVA, the object of
Polymorphism can be assigned to a variable of Object type. This use of a subclass object in
place of a super class object is a form of polymorphism.
The converse is not true. Therefore an object of super class cannot be assigned to a
variable of subclass type.
An object has only one form (the one that is given to it when constructed). Hence object
is constructor dependant. However, a variable is polymorphic because it can refer to objects of
different forms.
The Java programming language, like most object-oriented languages, actually permits
you to refer to an object with a variable that is one of the parent class types or of implemented
interface type. The interface might have been implemented in the parent class hierarchy.
The type of reference variable cannot be changed but the object that variable refers can
be changed to a compatible object. The reference variables type decides the methods of which
class can be executed.
Ex. : Refer Program 1.9
If you are a C++ programmer, there is an important distinction to be drawn between the
Java programming language and C++. In C++, you get this behavior only if you mark the
method as virtual in the source. In pure object-oriented languages, however, this is not normal.
C++ does this to increase execution speed.
Ex. : Refer Program 1.10
Homogeneous Collections
CETTM,MTNL,Mumbai
I 683
7 PA
You can create collections of objects that have a common class. Such collections are
called homogeneous collections.
For example :
Customer[] csa = new Customer[4];
csa [0] = new Customer();
csa [1] = new Customer();
csa [2] = new Customer();
csa [3] = new Customer();
Ex. : Refer Program 1.11
Heterogeneous Collections
The Java programming language has an Object class, which is the parent class of all
JAVA classes. So you can create virtual objects of either parent class or Object class and make
collections of all kinds of elements. These collections are called heterogeneous collections.
A heterogeneous collection is a collection of dissimilar items. In object-oriented
languages, you can create collections of many items. All have a common ancestor class i.e. the
Object class.
Every class is a subclass of Object, so you can use an array of Object as a container for
any combination of objects. The only items that cannot be added to an array of Object are
primitive variables. However, you can create objects from primitive data using wrapper classes,
as described in "Wrapper Classes"
Ex. : Refer Program 1.10
Instanceof Operator
Given that you can pass objects around using references to their parent classes,
sometimes you might want to know what actual objects you have. This is the purpose of the
instanceof operator.
Suppose the class hierarchy is extended so that you have the following :
public class Customer extends Object
public class SubclassSavingsAccount extends Customer
public class SavingsAccountPassbook extends SubclassSavingsAccount
public class VirtualMethodInvocation extends SavingsAccountPassbook
Remember that, while acceptable, extends Object is redundant. It is shown here only as
a reminder.
If you receive an object using a reference of type Customer, it might turn out to be a
SubclassSavingsAccount or a SavingsAccountPassbook. You can test it by using
instanceof operator.
If test for higher class hierarchy instance is to be made and an instance of its subclass is
also is to be tested then the instance of subclass is to be tested prior to instance of parent class
else parent class testing includes instance of subclass also. In this example the instance of
VirtualMethodInvocation is to be tested prior to the instance of SavingsAccountPassbook
class and so on.
In C++, you can do something similar using runtime-type information (RTTI).
Casting Objects
In circumstances where you have received a reference to a parent class, and you have
determined that the object is, in fact, a particular subclass by using the instanceof operator, you
can access the full functionality of the object by casting the reference.
If you do not make the cast, an attempt to execute cs[i].passBookHolderGetter() would
fail because the compiler cannot locate a method called passBookHolderGetter() in the
Customer class.
If you do not make the test using instanceof, you run the risk of the cast failing.
Generally, any attempt to cast an object reference is subjected to several checks :
1. Casts upward in the class hierarchy are always permitted and, in fact, do not
require the cast operator. They can be done by simple assignment.
2. For downward casts, the compiler must be satisfied that the cast is at least
possible. For example, any attempt to cast a SavingsAccount reference to a
Customer reference is not permitted, because the SavingsAccount is not a
Customer. The class to which the cast is taking place must be some subclass of
the current reference type.
3. In other cases if the compiler permits the cast, then the object type is checked at
runtime. For example, if it turns out that the instanceof check is omitted from the
source, and the object being cast is not in fact an object of the type it is being
cast to, then a runtime error (exception) occurs.
Ex. : Refer Program 1.12
CETTM,MTNL,Mumbai
I 683
9 PA
When you write code to call one of these methods, the appropriate method is chosen
according to the type of argument or arguments you supply.
Two rules apply to overloaded methods :
Varargs Method
The three overloaded methods all share the same functionality. It would be nice to
collapse these methods into one method. J25E version 5.0 now provides a feature, called
varargs or variable arguments, to enable you to write a more generic method.
CETTM,MTNL,Mumbai
I 683
11 PA
toString() Methods
Print methods are common in some languages, but most Java programs operate
differently. You can use System.out.println() to print any object. However for good results your
class should have a toString() method that formats the object's data in a sensible way and
returns a string. Otherwise all that is printed is the name of the class which is normally not what
you want. For example, a good toString() method for the CustomerModified class might be
public String toString() {
return (Account Number : + this.accountNumber + Account Name : +
this.accountName + Address : + this.address + Drawing Power : + this.drawingPower);
}
toString() methods should return a single line of text that does not contain any carriage
returns or linefeeds.
toString() methods are primarily for debugging.
toString() should not do a lot of fancy processing.
toString() methods should be quick.
The string returned by toString() should contain the name of the class, and names and
values of the fields that represent the state of the object, unless there are an excessive
number of such fields, in which case only the most important should be returned.
CETTM,MTNL,Mumbai
I 683
13 PA
Wrapper Classes
The Java programming language does not look at primitive data types as objects. For
example, numerical, boolean and character data are treated in the primitive form for the sake of
efficiency.
However the Java programming language provides wrapper classes to manipulate
primitive data elements as objects. Such data elements are wrapped in an object created
around them. Each Java primitive data type has a corresponding wrapper class in the java.lang
package. Each wrapper class object encapsulates a single primitive value.
Wrapper Class
Boolean
Byte
Character
short
Short
int
Integer
long
Long
float
Float
double
Double
All the wrapper classes except Character have two constructors, one that takes the
primitive value and another that takes the String representation of the value.
For instance :
Integer i1 = new Integer(50);
Integer i2 = new Integer("50");
The Character class constructor takes a char type element as an argument :
Character c = new Character('A');
Parser methods
The six parser methods are parseInt, parseDouble, parseFloat, parseLong, parseByte,
and parseShort. They take a String as the argument and convert it to the corresponding
primitive. They throw a NumberFormatException if the String is not properly formed.
For instance:
double d = Double.parseDouble("4.23");
It can also take a radix (base) as the second argument:
int i = Integer.parseInt("10011110",2);
Ex. : Refer Program 1.19
CETTM,MTNL,Mumbai
I 683
15 PA
Base conversion
The Integer and Long wrapper classes have methods like toBinaryString() and
toOctalString(), which convert numbers in base 10 to other bases.
For instance:
String s = Integer.toHexString(25);
Ex. : Refer Program 1.19