At the end of this chapter, you will be able to understand and use concepts and programs relating to
This chapter introduces you to one of the most powerful features of any objective-oriented language, i.e. inheritance. Inheritance is a tool offered by Java to create another class from an existing class. We call this creation as extending a class. In the literature, the class that is a starting point or source of extension is called base class. Java calls this a superclass. The class that is extended is called derived class. In Java, derived class is called subclass. A subclass can inherit all the members, both methods and attributes, and also can implement its own methods. Further, a subclass can override superclass methods. We also introduce you to concepts of abstract class and interfaces which are part of Java's concepts for extending from existing classes.
Inheritance class hierarchy shown in Figure 19.1. Student and Athlete derive qualities from base class person. We say these subclasses have inherited from Person. Class Person is called base class and in Java it is called Super, while Student and Athlete are called Subclasses. What can be inherited? Both member functions and member data can be inherited.
Figure 19.1 Inheritance hierarchy
Inheritance can be incorporated into our program by using a keyword extends. The following program shows a base class Super and a subclass Student.
Example 19.1a: Write a Java Program to Create a Super Class Person for and a Subclass Called Student and Show Simple Inheritance Concept.
1. package com.oops.chap19;
2. class Person {
3. // member data or attributes
4. String name; // name of the student
5. int idNo;
6. //access and mutator methods
7. int GetIdNo(){ return idNo;}
8. void SetIdNo(int id){ idNo=id;}
9. String GetName(){ return name;}
10. void SetName(String nm){ name=nm;}
11. public void DisplayData() {
12. System.out.println(“Basic Details are………”);
13. System.out.println(“Id Number:” + idNo);
14. System.out.println(“Name:” + name);}
15. }//end of class Person
Line No. 1: | defines our project package name as com.oops.chap19. |
Line Nos. 2 to 15: | define a base class Person. Line Nos. 4 and 5 declare two attributes of Person viz. String name and int idNo. |
Line Nos. 7 & 9: | are accessor methods and Line Nos. 8 and 10 are mutator methods. |
Line No. 11: | defines a method called DisplayData() for displaying the basic data of person. |
Compile the source file Person.java and store the class file Person.class in bin Directory. Refer to Chapter 15 for comprehensive compilation and execution instructions both for Java and eclipse environments.
Now, another team member would like to reuse the code we have developed for class Person. He is aware of attributes and methods of class Person. In order to reuse he has to perform three tasks as shown in Example 19.1b:
Example 19.1b: Student1Demo.java A program to show single inheritance from class Person in Example 19.1.
//Student1Demo.java
1. package com.oops.chap19;
2. import com.oops.chap19.Person;
3. class Student1 extends Person {
4. // member data or attributes
5. private double totalMarks;
6. private String grade;
7. //access and mutator methods
8. double GetMarks(){ return totalMarks;}
9. void SetMarks(double mks ){ totalMarks=mks;}
10. String GetGrade(){ return grade;}
11. void SetGrade(String gd){ grade=gd;}
12. //public method
13. public Student1 ComputeGrade(Student1 std) {
14. if( totalMarks >=80.0) std.grade=”A”;
15. else if (totalMarks>= 60.0) grade=”B”;
16. else if (totalMarks>= 50.0) grade=”C”;
17. else grade=”D”;
18. return std;
19. }
20. }//end of class Student
21. // Driver class
22. class Student1Demo{
23. public static void main(String[] args){
24. // create an object of Student
25. Student1 std = new Student1();
26. std.SetMarks(97.8);
27. std.SetName(“Ramesh”); // we have called super method
28. std.SetIdNo(50595);
29. std=std.ComputeGrade(std);
30. std.DisplayData();
31. System.out.println(“Details of Subclass Student: “);
32. System.out.println(“Total Marks:” + std.GetMarks());
33. System.out.println(”Grade:“ + std.GetGrade());}
34. }//end of class Student1Demo
Output: Basic Details are………
Id Number:50595
Name:Ramesh
Details from Sub class Student:
Total Marks:97.8
Grade:A
Access specifiers play an important role in inheritance relationships. We have learnt that if we foresee inheritance and we need to allow subclass to access the super's members, we need to declare them as protected.
If we declare the members as private, then they are visible inside a class only. They are not visible to subclasses or outside the class.
Default access specifiers means they are public to package. This mean that all the classes in the package can access them as if they are public.
Public specifier means they are accessible to all outside members.
Example 19.2a: Person2.java With Protected and Private Data Members.
1. package com.oops.chap19;
2. class Person2 {
3. // member data or attributes
4. protected String name; //protected
5. protected int idNo;
6. private double salary;
7. //access and mutator methods
8. int GetIdNo(){ return idNo;}
9. void SetIdNo(int id){ idNo=id;}
10. String GetName(){ return name;}
11. void SetName(String nm){ name=nm;}
12. double GetSal(){ return salary;}
13. void SetSal(double sl){ salary=sl;}
14. public void DisplayData() {
15. System.out.println(“Person Details are………”);
16. System.out.println(“Id Number:” + idNo);
17. System.out.println(“Name:” + name);
18. }
19. public void DisplaySal(){
20. System.out.println(“Salary:” + salary);}
21. }//end of class Person
Compile it as Person2.java
In the example that follows, we will show you Student2Demo class inheriting protected members and defining its own private data members. Private data members are not visible outside the class.
Example 19.2b: Student2Demo.java Inheriting From Super Person2
//Student2Demo.java 1. package com.oops.chap19; 2. import com.oops.chap19.Person2; 3. class Student2 extends Person2 { 4. // member data or attributes 5. private double totalMarks; 6. private String grade; 7. //access and mutator methods 8. double GetMarks(){ return totalMarks;} 9. void SetMarks(double mks ){ totalMarks=mks;} 10. String GetGrade(){ return grade;} 11. void SetGrade(String gd){ grade=gd;} 12. //public method 13. public Student2 ComputeGrade(Student2 std) { 14. if( totalMarks >=80.0) std.grade=”A”; 15. else if (totalMarks>= 60.0) grade=”B”; 16. else if (totalMarks>= 50.0) grade=”C”; 17. else grade=”D”; 18. return std; 19. } 20. }//end of class Student 21. // Driver class 22. class Student2Demo{ 23. public static void main(String[] args){ 24. // create an object of Student 25. Student2 std = new Student2(); 26. std.SetMarks(97.8); 27. std.SetName(“Ramesh”); // we have called super method 28. std.SetIdNo(50595); 29. //std.salary=19000.00;// error. salary is private in person2 30. std.SetSal(30000.00);//ok as we are using Set method 31. std=std.ComputeGrade(std); 32. std.DisplayData(); 33. System.out.println(“Details from Sub class Student: “); 34. System.out.println(“Total Marks:” + std.GetMarks()); 35. System.out.println(”Grade:“ + std.GetGrade()); 36. //System.out.println(”Salary“+ std.salary);//Error. salary not visible 37. System.out.println(“Salary : “+ std.GetSal());} 38. }//end of class Student2Demo Output: Person Details are……… Id Number:50595 Name:Ramesh Details from Sub class Student: Total Marks:97.8 Grade:A Salary : 30000.0
Line No. 29: | //std.salary=19000.00;// error Since salary is private and is not visible outside the class> However, Line No 30 std.SetSal(30000.00);//ok as we are using Set method. The same concept holds good for Line No 37as well. |
Line No. 32: | is calling DisplayData() of super and basic data is displayed. However, for display of member data belonging to Student2, use is made of public accessory methods GetMarks() and GetSal(), etc., as shown in Line No 37. |
In the examples we have covered so far, we have used mutator methods like SetSalry() to set the private member data. But we know that the best way to initialize the object is by using constructors. A constructor can set the member data and initialize the object. But when inheritance relationship is involved and when we want to create an instance of subclass, we need to constructor of super first, so that super's constructor can make its part of the object and then subclass constructor completes its work of initialization with its part and then only the complete object is ready. Then how to call super's constructor. By simply using super keyword. The next example highlights the usage of keyword super.
Example 19.3a: Person2b.java A Super Class for Demonstrating Use of Super
1. package com.oops.chap19;
2. class Person2b {
3. // member data or attributes
4. protected String name; //protected
5. protected int idNo;
6. //Over loaded constructors
7. Person2b()
8. {System.out.println(“Super Default Const called “);
9. name=”NoName”;idNo=0;}
10. Person2b(String nm, int id)
11. {System.out.println(“Super(name,idNO) called”);
12. name=nm;idNo=id;}
13. Person2b(Person2b per)
14. {System.out.println(“Super(object) Const called “);
15. name=per.name;idNo=per.idNo;}
16. //access and mutator methods
17. public void DisplayData() {
18. System.out.println(“Person Details are………”);
19. System.out.println(“Id Number:” + idNo);
20. System.out.println(“Name:” + name);
21. }
22. }//end of class Person
Line Nos. 6, 9 & 12: | are constructors defined by Person2b. These are overloaded constructors and will be called by class that is inheriting from Person2b using the keyword super. |
Example 19.3b: Student2bDemo.java To Show Calling of Super Constructors
1. package com.oops.chap19;
2. import com.oops.chap19.Person2b;
3. class Student2b extends Person2b {
4. // member data or attributes
5. private double totalMarks;
6. private String grade;
7. //create object of Student2b by calling super constructor
8. Student2b(Student2b std2b){
9. super(std2b);
10. totalMarks=std2b.totalMarks;
11. grade=std2b.grade;
12. }
13. //constructor with all parameters given
14. Student2b(String nm, int rn, double tm, String gd){
15. super(nm,rn);
16. totalMarks=tm;
17. grade=gd;
18. }
19. //access and mutator methods
20. double GetMarks(){ return totalMarks;}
21. void SetMarks(double mks ){ totalMarks=mks;}
22. String GetGrade(){ return grade;}
23. void SetGrade(String gd){ grade=gd;}
24. //public method
25. public Student2b ComputeGrade(Student2b std) {
26. if( totalMarks >=80.0) std.grade=”A”;
27. else if (totalMarks>= 60.0) grade=”B”;
28. else if (totalMarks>= 50.0) grade=”C”;
29. else grade=”D”;
30. return std;
31. }
32. public void DisplayData(Student2b std) {
33. super.DisplayData();
34. System.out.println(“Total Marks:” + std.GetMarks());
35. System.out.println(”Grade:“ + std.GetGrade());
36. }//end of class Student
37. }
38. // Driver class
39. class Student2bDemo{
40. public static void main(String[] args){
41. // create an object of Student
42. Student2b std1 = new Student2b(“Ramesh”,50595,97.8,”X”);
43. std1.ComputeGrade(std1);
44. std1.DisplayData(std1);
45. System.out.println(“Total Marks:” + std1.GetMarks());
46. System.out.println(”Grade:“ + std1.GetGrade());
47. }
48. }//end of class Student2bDemo
Line No. 2: | shows that Student2b extends to Person2b. This means that it has access to all public and protected members like protected String name, protected int idNo and method DisplayData() of Person2b. |
Line Nos. 4 & 5: | declare Student2b private data and Line Nos. 19–23 define mutator and accessor methods for these private variables. Interesting and new points in this program are in Line Nos. 8 to 18 that show overloaded constructors for Student2b Line No. 8 Student2b(Student2b std2b) receives std2b an object as parameter and calls super(std2) in Line No. 9. Remember super of Student2b is Person2b and accordingly Person(per object) as shown in Line No. 12 of Example 19.3a will be called. So Person2b(per) will set name and id number in Line No. 11 and constructor of Student2b will set totalMarks and grade in Line No. 10 and 11 of Example 19.3b. |
Line No. 42: | creates an object of Student2b by supplying all the arguments like name, idNo, total Marks, and grade. Line No 43 calculates grade. |
Line No. 44: | calls DisplayData() that in turn calls super.Display() data to display data pertaining to Person2b such as name and idNo as shown at Line Nos. 16–19 (19.3a) and local private variables like totalMarks and grade to accessor methods shown in Line Nos 19 and 22. |
Inheritance relationship allows a subclass to inherit all the protected members of a superclass. Importantly, it can decide to override them and implement its own version. This is like, your daddy has a car. As a descendant, you have the privilege to use Daddy's car or buy a scooter for your exclusive movement. When you call for a transport, obviously you will get a scooter.
What is overriding: Superclass method overriding means the same name and return type in the subclass as that defined in the superclass. But the base class will have different implementations. For example, superclass Person defines two methods, namely, Work() and Learn():
public void Learn()
{ System.out.println(“
Persons learn general subjects…”;}
public void Work()
{ System.out.println(“
Persons work at work spots………..…”;}
Subclass, if it does not define these functions once again, it can use superclass learn() or Work(). But if it wants its own implementation, different from base class, it can define these methods in its class definition.
public void Learn()
{System.out.println(“
Students learn professional subjects…”;}
public void Work()
{System.out.println(“
Students work at college laboratories…”;}
When subclass object calls these functions, it will get derived class functionality only but NOT the base class functionality. The concepts are shown in our next example.
Example 19.3c: A Program to Show Super Class Methods Overriding by Subclass
1. package com.oops.chap19;
2. public class Person3 {
3. public void Learn(){ System.out.println(“Persons Learn “);}
4. public void Work(){System.out.println(“Persons work at work spots”);}
5. }//end of class Person3
Compile it as Person3.java
Line No. 3 & 4: | declare two public methods called Learn() and Work() |
Student3 Class and StudentDemo To Show Overriding of Super Methods
1. package com.oops.chap19; 2. import com.oops.chap19.Person3; 3. class Student3 extends Person3 { 4. //public method 5. public void Learn() 6. {System.out.println(“Students Learn at college”);} 7. public void Work() 8. {System.out.println(“Students work at college labs”);} 9. public void Play() 10. {System.out.println(“Students play at college grounds”);} 11. }//end of class Student3 12. // Driver class 13. class StudentDemo3{ 14. public static void main(String[] args){ 15. // create an object of Student 16. Student3 std = new Student3(); 17. System.out.println(“sub class calls over ridden methods”); 18. std.Learn(); 19. std.Work(); 20. System.out.println(“sub class calls its own method”); 21. std.Play(); 22. } 23. }//end of class Student1Demo Output: sub class calls over ridden methods Students Learn at college Students work at college labs sub class calls its own method Students play at college grounds
Line No. 3: | shows that Student3 extends to Person3. Accordingly, we have imported Student3 in Line No 2. Line No. 9 shows that subclass can define its own method called Play() and use it in Line No 21. In Line Nos. 5 and 7, subclass Student3 overrides base class methods with its own implementations. So when Student3 object std calls Learn() and Play() in Line Nos. 18 and 19, its own methods are called and supermethods are overridden. |
Examples 19.1 to 19.3 have shown single inheritance. We can also have multilevel inheritance. This means that Student can derive from Person and Athlete can then be derived from Student. It is like Grandfather, Father and Son relationship. When such multilevel inheritances are planned, remember that all subclasses can have access to all the superclasses. This means that the Son can have access to protected and public members of both Father and Grandfather. We have shown the multilevel inheritance at Figure 19.2 between the superclass Person and multilevel inheritance as Student and Athlete.
Figure 19.2 Multilevel inheritance
We have already developed code for Person2b and Student2b. We now want to create a new class called Athlete2b from Student2b. This means that we want to create a new class by extending an existing class. There is no need to write or duplicate the code for Strudent2b or Person2b again. We can simply import these classes and create a new class by extending, as shown in our next example. This is the power of inheritance and demonstration of the reuse feature of Java.
Example 19.4: Athlete2bDemo.java
1. package com.oops.chap19; 2. import com.oops.chap19.Student2b; 3. class Athlete2b extends Student2b { 4. // member data or attributes 5. private String sport; 6. private String level; // S/N/I for state and N for national 7. //create object of Athlete2b by calling super constructor 8. Athlete2b (Athlete2b ath2b){ 9. super(ath2b); 10. sport=ath2b.sport; 11. level=ath2b.level; 12. } 13. //constructor with all parameters given 14. Athlete2b (String nm, int rn, double tm, String gd, String sp,String lv){ 15. super(nm,rn,tm,gd); 16. sport=sp; 17. level=lv; 18. } 19. //access and mutator methods 20. public String GetSport(){ return sport;} 21. public String GetLevel(){return level;} 22. //public method 23. public void DisplayData(Athlete2b ath2b) { 24. super.DisplayData(ath2b); 25. System.out.println(“Details from Athlete2b are :”); 26. System.out.println(“Sport:” + ath2b.GetSport()); 27. System.out.println(“Level:” + ath2b.GetLevel()); 28. }//end of class Student 29. } 30. // Driver class 31. class Athlete2bDemo{ 32. public static void main(String[] args){ 33. // create an object of Athlet 34. Athlete2b ath1 = new Athlete2b (“Ramesh”,50595,97.8,”X”,”FootBall”,”S”); 35. ath1.ComputeGrade(ath1); 36. ath1.DisplayData(ath1); 37. } 38. }//end of class Athlete2bDemo Output: Super(name,idNO) called Person Details are…… Id Number:50595 Name:Ramesh Details from Student2b are : Total Marks:97.8 Grade:A Details from Athlete2b are : Sport:FootBall Level:S
Hitherto, what we have shown is overriding of super methods by Java's subclasses. This feature is exploited by Java to give programmers a powerful tool to resolve the method overriding at run time rather than at compile time. A reference made to super can refer to any one of the overridden subclass methods. But which overridden method is to be called? Java simply decides this based on the type of the object referred to at run time.
Therefore, we can say that whichever type of object is referred to by reference to super class, that object's particular overridden method is called. We will explain this with a simple program. Refer to Figure 19.3. There is a super class called Shape, and two subclasses derived from Shape are Circle and Triangle. Super declares a method void FindArea() which is overridden by both Circle and Triangle with their own implementation. Our next example shows how we can use run-time polymorphism feature and call the implementation based on the type of object at run time.
Figure 19.3 Run time polymorphism
Example 19.5: RunTimePoly.java To Demonstrate Run-time Polymorphism Feature of Java.
//RunTimePoly.java a programme to shown run time ploy morphism 1. package com.oops.chap19; 2. class Shape{ 3. void FindArea(){ 4. System.out.println(“Inside Shape. No definite Area”);} 5. }// end of Shape 6. class Circle extends Shape{ 7. void FindArea(){ 8. System.out.println(“Inside Circle. Area=PI*r*r”);} 9. }// end of Circle 10. class Triangle extends Shape{ 11. void FindArea(){ 12. System.out.println(“Inside Triangle. Area=0.5*base*alt”);} 13. } // end of class Triangle 14. class RunTimePoly { 15. public static void main(String[] args) { 16. // create object to classes 17. Shape shp = new Shape();//object of Shape 18. Circle circ = new Circle();//object of Circle 19. Triangle trg = new Triangle();//object of Triangle 20. System.out.println(“A ref to super can refer to sub class over ridden Methods”); 21. System.out.println(“Therefore create a ref to super”); 22. Shape refsuper; // reference to super class Shape 23. System.out.println(“A refrence to super “); 24. refsuper=shp; // refsuper refers to Shape object 25. refsuper.FindArea(); 26. System.out.println(“A refrence to Circle “); 27. refsuper=circ; // refsuper refers to Circle object 28. refsuper.FindArea(); 29. System.out.println(“A refrence to Triangle “); 30. refsuper=trg; // refsuper refers to Triangle object 31. refsuper.FindArea();} 32. }// end of runtime poly Output: A refrence to super can refer to sub class over ridden Methods Therefore create a referecne to super A refrence to super Inside Shape. No definite Area A refrence to Circle Inside Circle. Area=PI*r*r A refrence to Triangle Inside Triangle. Area=0.5*base*alt
Line Nos. 17–19: | create objects to classes Shape, Circle and Triangle. Shape is super class and Circle and triangle are subclasses, as shown in Line Nos. 6 and 10. Each subclass Circle and Triangle has overridden super method FindArea() in Line Nos. 8 and 11. |
Line No. 22: | obtains a reference to super class object. Line Nos. 24, 27 and 30 show that reference is made to refer to objects of Shape, Circle and Triangle. Therefore, in Line Nos. 25, 28 and 31, the corresponding overridden methods are called. |
When we need to ensure that all subclasses have to share common methods but at the same time have their own implementations, we use abstract class. Abstract class will have one or more abstract methods. An abstract need not have any abstract method at all.
An abstract method is a method that is declared but not defined. It is declared with the keyword abstract, and has a header like any other method, but ends with a semicolon and contains no method body. The syntax is: abstract type Method Name (arguments);
A non-abstract class is sometimes called a concrete class.
An abstract class cannot be instantiated because it contains abstract methods. However, subclasses derived from abstract class can have their own implementations. Let us revisit our example at 19.5, but this time we would declare Shape as abstract class.
Example 19.6: Abstract.java A Program to Show Abstract Class and Methods Usage
1. package com.oops.chap19;
2. abstract class Shape1{
3. abstract void FindArea(); // abstract method
4. public void DisplayCommon(){
5. System.out.println(“Inside Shape. Exiting the Shape1 common message”);
6. }
7. }//end of class Shape1
8. class Circle1 extends Shape1{
9. void FindArea(){
10. System.out.println(“Inside Circle1. Area=PI*r*r”);
11. super.DisplayCommon();// display common message thru super abstract class
12. }
13. }// end of Circle1
14. class Triangle1 extends Shape1{
15. void FindArea(){
16. System.out.println(“Inside Triangle1. Area=0.5*base*alt”);
17. super.DisplayCommon();
18. }
19. }//end of Triangle1
20. class AbstractDemo{
21. public static void main(String[] args) {
22. // create object to classes
23. //Shape1 shp = new Shape1();//error.can’t instantiate abstract class
24. Circle1 circ1 = new Circle1();//object of Circle
25. Triangle1 trg1 = new Triangle1();//object of Triangle
26. System.out.println(“A ref to super calls sub class over ridden Methods”);
27. System.out.println(“create a ref to super”);
28. Shape1 refsuper; // reference to super class Shape
29. System.out.println(“A ref to super : refsuper is created”);
30. System.out.println(“ref to refer to object of Circle1 “);
31. refsuper=circ1;
32. refsuper.FindArea();
33. System.out.println(“ref to refer to object of Triangle “);
34. refsuper=trg1;
35. refsuper.FindArea();
36. }
37. }
Output: A refrence to super can refer to sub class over ridden Methods
Therefore create a referecne to super
A refrence to super : refsuper is created
refrence made to refer to object of Circle1
Inside Circle1. Area=PI*r*r
Inside Shape. Exiting the Shape1 common message
refrence made to refer to object of Triangle
Inside Triangle1. Area=0.5*base*alt
Inside Shape. Exiting the Shape1 common message
Line No. 2: | declares an abstract class. It is declared as abstract because it has one abstract method defined in Line No. 3, only name and no body: abstract void FindArea(); |
Line No. 4: | declares a non-abstract method: public void DisplayCommon() that is used to implement a common functionality to all derived subclasses. What is common to all, it is better to implement it at abstract class level instead of at each subclass. |
Line Nos. 8 to 19: | declare and define concrete methods in classes Circle1 and Triangle1. Note how at the end of specialized method called FindArea() these methods are invoking common functionality, an exit routine we can say by calling super.DisplayCommon(); in Line Nos. 11 and 17. |
Refsuper is a reference created in Line No. 28 and it is made to refer to object of Circle1 and Triangle1 in Line Nos. 31 and 34.
In the previous chapter, we have shown how final keyword can be used to define variables and maintain their values constant and unchanged during the running of the program.
Final qualifier can be used with methods also. You are aware that in inheritance, the derived class can override base class methods with its own implementation. When we do not want such a thing to happen, we need to declare the method in base class as final. For example:
Example 19.7: Java Code Segment to Show the Use of Final Qualifier for a Method. Constructors and Destructors of a Class
class Person {
final void Update() { //update code here. Final Methods. Cannot be inherited}
} // end of person
class Student extends Person {
void update() { // Error cannot be inherited}
} // end of student
When we do not want a class to be inherited we declare a class as final. As class cannot be inherited, then automatically by default all the members inside a final class are considered as final and hence cannot be inherited.
Example 19.8: Java Code Segment to Show the Use of Final Qualifier for a Class. Constructors and Destructors of a Class
final class Person {
void Update() { //update code here. Final Methods. Can not be inherited}
} // end of person
class Student extends Person { // error Student cannot extend to Person(final class)
Void update() { // Error cannot be inherited}
} // end of student
By now, we appreciate the power of run-time polymorphism and reuse of code already written. The objects we create are automatically treated as subclasses for the class called Object in java.lang package. What is the advantage gained by this?
The Object class contains several useful static methods that can be used directly without creating object. Now that all object user creates are treated as subclasses, all user-created objects will get access to the static method in meta class Object in package java.lang. The methods with final specifier cannot be overridden. Methods supported by the object class are given in Table 19.1.
Table 19.1 Static and final methods of object class
Example 19.9: ObjectDemo.java A Java Program to Show the Use of Static Method of Object Class
1. package com.oops.chap19; 2. class Person4 implements Cloneable{ 3. String name; 4. Person4(String nm){name=nm;} 5. public String Getname() {return name;} 6. public void DisplayData() { 7. System.out.println(“Person Details are………”); 8. System.out.println(“overriden toString() Method:” + toString()); 9. System.out.println(“Obj Details from static method hashcode()”); 10. System.out.println(“Object Hash Code :” + hashCode());} 11. public String toString() 12. {String stg; 13. stg = “Name :” + Getname(); 14. return stg;} 15. public void CompareObjects(Person4 per2){ 16. System.out.println(“ using equals(obj) static method”); 17. if (this.equals(per2)) 18. System.out.println(“Per1& Per2 are same.”); 19. else System.out.println(“Per1 & Per2 are NOT same.”);} 20. public Object CloneObj()throws CloneNotSupportedException 21. {return super.clone();} 22. }//end of class Person 23. public class ObjectDemo { 24. public static void main(String[] args) throws CloneNotSupportedException 25. { 26. //Two different objects. Their references are NOT same 27. // But Content same 28. System.out.println(“Two objects per1&2 with same content”); 29. Person4 per1 = new Person4(“Salman”); 30. Person4 per2 = new Person4(“Salman”); 31. per1.CompareObjects(per2); 32. System.out.println(“Displaying per1 data”); 33. per1.DisplayData(); 34. System.out.println(“Clone per1 object to per3”); 35. Person4 per3 = (Person4)per1.CloneObj(); 36. System.out.println(“Displaying per3 data”); 37. per3.DisplayData(); 38. } 39. } Output: Creating two objects per1 and per2 with same content using equals(obj) static method Per1 & Per2 are NOT same. Displaying per1 data Person Details are……… Using overriden toString() Method:Name :Salman Object Details from static method hashcode() of Object class are……… Hash Code of Object:1671711 Clone per1 object to per3 Displaying per3 data Person Details are……… Using overriden toString() Method:Name :Salman Object Details from static method hashcode() of Object class are……… Hash Code of Object:11394033
Line No. 2: | declares a class Person4 implementing an interface called Cloneable. Cloneable is called interface. More details about the interface in succeeding sections. All the methods described by interface are available to Person4. |
Line No. 4: | is a constructor that assigns data to name as per argument supplied. |
Line No. 10: | overrides the static method toString() method. Hence when you call toString() as in Line No. 8, own overridden method is called. |
Line No. 11: | defines the overridden tostring() method. Line No. 15 is about Object CompareObjject(Person4 obj) that takes in object and compares the argument object with object that is invoking the object. It checks the reference of both objects and if they are equal, returns true and else returns false. |
Line No. 19: | public Object CloneObj()throws CloneNotSupportedException is a public method CloneObj()that returns clone using clone() method of Object class. |
Line No. 19 & 24: | throws Clone Not Supported Exception Line No. 17 this refers to object that has invoked the method CompareObjects() |
As a developer, you would like to keep all your work together so that you can reuse them in future if needed. We would like to keep all our work as a “package”. Suppose you are working in a company called “oops.com”, then it is customary to create package as “com.oops”. Now we are writing programs for Chapter 19. Hence, we will name our package as “com.oops.chap19”. Refer to Figure 15.7. Path variable will link up to c:Oopajavaexamplesrc. It is your package statement, package com.oops.chap19; which will link to com.oops.chap19.
So what is a package? A package is collection of all related class files into a group so that they can be reused by importing them into other classes and thus aid in enhancing
The concepts and commands to be used for package and path and class path have been dealt in detail in Chapter 15 and Section 15.5. The user is strongly advised to go through the concepts and examples to get practice. Here, we concentrate only on amplification of a few relevant concepts like reusability, etc.
Now go to bin directory and type the command to execute java program giving full package path.
C:OopsJavaexamplesin>java com/oops/chap19/Date1
Note that since it's a simple program, we have executed it from bin directory. For large programs or programs with several classes, we would write a driver program and place the class program in directory TestDriver. Then we need to execute java command from TestDriver directory. Chapter 15 gives you details of setting the path and class path.
Chapter 15 (Section 15.6.2) gives full details and settings required for path and class path variables. Setting path is essential if we want to run java executables from any directory without stating full path name each time. Class path, on the other hand, is a message from you to Java environment, where to search for your class files.
Package means grouping all relevant classes so that they can be reused. Therefore, all the class files in the same package are public up to package level and hence need not be imported. However, class files belonging to outside packages are required to be imported. For example, we need to import java.util.*; to get access to class file in package java.util.
Example 19.10a: Date1.java A Program to Develop Reusable Class Date1 Using Package and Import of Class
/* Date1.java Date1 class shows date in dd:mm:yy format & converts to dd:mmm:yy format*/
1. package com.oops.chap19;
2. public class Date1 {
3. private int dd;
4. private int mm;
5. private int yy;
6. //constructor for Date1
7. Date1(int d, int m,int y){dd=d;mm=m;yy=y;}
8. //validate date
9. public void validateDate(int d,int m,int y)
10. {dd= ((d>=0 && d<=31 )?d:0);
11. mm= ((m>=0 && d<=12 )?m:0);
12. yy= ((y>=1900 && d<=1999)?y:0 );
13. }// end of validateDate()
14. // change date format to dd-mmm-1910 Ex 01:Jan:10 format
15. public String ConverttoMMM(int mm){
16. String mmm=””;
17. switch(mm)
18. { case 1 : mmm=”JAN”;break;case 2 : mmm=”FEB”;break;
19. case 3 : mmm=”MAR”;break;case 4 : mmm=”APR”;break;
20. case 5 : mmm=”MAY”;break;case 6 : mmm=”JUN”;break;
21. case 7 : mmm=”JUL”;break;case 8 : mmm=”AUG”;break;
22. case 9 : mmm=”SEP”;break;case 10 : mmm=”OCT”;break;
23. case 11: mmm=”NOV”;break;case 12 : mmm=”DEC”;break;
24. }
25. return mmm;
26. }
27. public String toDDMMMYYString()
28. {return String.format(“%d:%s:%d”,dd,ConverttoMMM(mm),yy);}
29. public String toString()
30. {return String.format(“%d:%d:%d”,dd,mm,yy);}
31. }// end of Date1
Example 19.10b: Datetester.java A Driver Program to Test Date1 at Example 19.10a
1. package com.oops.chap19;
//import com.oops.chap19.Date1; Need not be imported because same package
2. public class Date1tester{
3. public static void main(String[] args) {
4. // intialize the Date1 object
5. Date1 date = new Date1(19,11,10);
6. System.out.println(“date in<dd:mm:yy>format”+ date.toString());
7. System.out.println();
8. System.out.println(“date in<dd:mm:yy>format”+ date.toString());
9. System.out.println(“date in<dd:mmm:yy>format”+ date.toDDMMMYY String());
10. }
11. }//end of Date1tester class
Output : The Given Date is …….
date in<dd:mm:yy>format19:11:10
date in<dd:mmm:yy>format19:NOV:10
Both Datetester and date1 belong to the same package. Hence, Date1 need not be imported. Hence, we have commented it out.
Line No. 2: | delcares our driver class Datetester |
Line No. 4: | creates an object date of Date1 by calling the constructor of Date1. This is how we will achieve reusability. |
Line Nos. 8 & 9: | call methods date.toString()&date.toDDMMMYYString()of Date1 to display date in two different formats. |
The access specifiers are public, private, protected and default also called friendly, i.e. public up to package level. These specifiers act on classes, subclasses and packages. Java allows a special definition called private protected to give visibility to all subclasses ,wherever they are present independent of packages. The visibility is specified in Table 19.2. OK stands for visible. NO stand for not visible.
Note that Java allows a special access specifier in private protected, when we want to provide access to subclass anywhere, independent of package.
In Section 19.8, we have shown you the power of dynamic polymorphism offered by java. It provided a facility wherein a reference to super can refer to any one of the subclass overridden methods based on the type of object. We have further dealt with abstract classes that contain abstract methods. Abstract methods will have only the head terminated by a semicolon, but no body showing the implementation. We have also learnt that an abstract class cannot be instantiated since it has abstract methods. However, a reference to abstract class can be created that can then be made to refer to objects of subclasses.
Java permits only single inheritance and multilevel inheritance. A subclass can have only one super. Then how will java solve the problems wherein more than one super is required? The solution is a powerful tool provided by Java called interface. A class in Java can extend only to one super, but it can implement several Interfaces.
Refer to Figure 19.4. It shows a situation wherein super, called interface rather than a class, has abstract methods. Subclasses called Circle and Triangle implement all abstract methods. Also note that the dotted arrow pointing to interface rather than a solid arrow. This is notation as per modelling language UML.
Figure 19.4 Interface in Java
A second feature of interface is that it solves ambiguity problems associated with inheriting from more than one super. Java does not support multiple inheritances, meaning that it does not support extending to more than one super at a time to avoid ambiguities in Inheritance relationships. This problem is solved by Java by allowing multiple implementations. A class can extend to only one super, but it can implement several interfaces. This situation is shown in Figure 19.5. The syntax is:
Figure 19.5 Box class extends to shape, but can implement several interfaces
class Class extends Superclass implementsInterface1, Interface2
Example : class BoxShape extends Shpe implements Volume, Area
An interface is declared with the keyword interface instead of the keyword class. An interface may contain only abstract methods and definitions of constants (i.e., final variables). The keyword abstract before each method is optional.
When a class extends an interface, it may implement (define) some or all of the inherited abstract methods. A class must itself be declared abstract if it inherits abstract methods that it does not define.
Interface definition starts with keyword interface instead of class. Ex public interface Shape. Interface can be public or default specifier. Interface can hold only method name and no implementation. This means that all the methods are abstract methods. However, there is no need to use the keyword abstract in front of interface. An interface can also define final and static declarations. For example, we show three abstract methods in an interface called Shape in Example 19.11a. The concept diagram is shown in Figure 19.6.
Figure 19.6 Circle and triangle classes implement shape interface
Example 19.11a: Shape.java Interface Shape With Only Abstract Methods
1. package com.oops.chap19;
2. public interface Shape {
3. final static double PI = 3.141519;
4. // abstract methods. Only Head no body.
5. //Using key word abstract is optional
6. double ComputeArea(double x);
7. double ComputePerimeter(double x);
8. void DrawShape();
}// end of interface shape
Example 19.11b: ShapeTest.java Circle and Square classes implement interface
1. package com.oops.chap19; 2. // Circle 3. class Circle2 implements Shape 4. {public double ComputeArea(double radius){ 5. double area=0; area = PI*radius*radius; 6. return area; 7. } 8. public double ComputePerimeter(double radius){ 9. double perim=0;perim = 2*PI*radius;return perim;} 10. public void DrawShape(){ 11. System.out.println(“Draw Circle Shape here!”);} 12. }// end of class Circle1 13. class Square implements Shape 14. {public double ComputeArea(double side){ 15. double area=0; area = side*side;return area;} 16. public double ComputePerimeter(double side){ 17. double perim=0;perim = 4*side;return perim;} 18. public void DrawShape(){ 19. System.out.println(“Draw Square Shape here!”); } 20. }// end of class Square 21. class ShapeTest{ 22. public static void main(String[] args){ 23. //Create a reference to Interface Shape 24. Shape shp; 25. //Create objects of sub classes 26. Circle2 circ = new Circle2(); 27. Square sqr = new Square(); 28. // make ref to refer to Circle 29. shp=circ; 30. System.out.println(“Area of Circle”+ shp.ComputeArea(10.0)); 31. System.out.println(“Perim of Circle”+ shp.ComputePerimeter (10.0)); 32. shp.DrawShape(); 33. System.out.println(); //blank line 34. shp=sqr; 35. System.out.println(“Area of Square”+ shp.ComputeArea(10.0)); 36. System.out.println(“Perim of Square”+ shp.ComputePerimeter (10.0)); 37. shp.DrawShape(); 38. } 39. }
As interface Shape and implementing classes belong to the same package, there is no need to import the Shape interface.
18.218.212.102