Scrigroup - Documente si articole

     

HomeDocumenteUploadResurseAlte limbi doc
AccessAdobe photoshopAlgoritmiAutocadBaze de dateCC sharp
CalculatoareCorel drawDot netExcelFox proFrontpageHardware
HtmlInternetJavaLinuxMatlabMs dosPascal
PhpPower pointRetele calculatoareSqlTutorialsWebdesignWindows
WordXml

AspAutocadCDot netExcelFox proHtmlJava
LinuxMathcadPhotoshopPhpSqlVisual studioWindowsXml

Inheritance and Object-Oriented Programming

java



+ Font mai mare | - Font mai mic





Inheritance and Object-Oriented Programming

Inheritance

The technique of deriving new class definitions from an existing class definition is known as inheritance. Here are some reasons for using inheritance:

  • Reuse of predefined, well-tested classes
  • Standardization of behaviors across a group of classes
  • Ability to use members of a family of classes interchangeably in methods

With inheritance, the methods of the existing classes can be reused or changed. New attributes, fields, or data members, and methods can be added to adapt them to new situations.

Inheritance defines 'is a' relationships among classes and objects. Every object represents this 'is a' relationship to its class. All objects inherit from the class that defines them. For example, in the code shown in Figure 1, the object referenced by f1 'is a' Fish. It inherits from the class Fish

In Figure , the object referenced by c1 'is a' Cat. It inherits its data and behavior from the class Cat

The Fish and Cat classes define both common and different behaviors and data. The commonality of behaviors across some classes is the basis for inheritance. The programmer defining these classes could also define a class Animal that describes the data and behaviors common to theFish and Cat classes. The inheritance model applied to these classes would be one where the Animal class is the parent class. The parent class would define common behaviors for the Fish and Cat classes. TheFish and Cat classes each inherit common behaviors from the parent class. The Fish and Cat classes also define their own adaptations of these behaviors, which include new data and new behaviors. There exists an 'is a' relationship between Animal, Fish, and Cat. A Fish is an Animal, and a Cat is an Animal. This 'is a' relationship is the key concept of inheritance in object-oriented technology. Java allows 'is a' relationships to exist between classes. The Java API defines all classes as inheriting from the class Object, which is at the ultimate root of all class hierarchies. When discussing class hierarchy, defining explicit inheritance from the Object class is not required. The Animal class automatically extends from Object. Since the Fish class extends from Animal, theFish class has all the methods and attributes of the Object class.

With inheritance the 'is a' relationship extends to the root of the hierarchy. The object referenced by f1 'is a' Fish and 'is an' Animal. The object referenced by c1 'is a' Cat and 'is an' Animal. The Animal'is an' Object as shown in Figure 3.

The 'is a' relationship between Animal, Fish, and Cat can be thought of as "is a plus additional functionality". Cat and Fish are examples of subclasses of the Animal class that provide additional functionality, such as the name attribute, getName() method and the play() method of the Cat class. Subclasses are classes that derive a core set of attributes and behaviors from another class. The class they derive from is referred to as the superclass. Another set of terms used to describe this relationship is that of a parent class, which is Animal, and child class, which is Cat or Fish. In Figure 3, the Animal class is the superclass for Cat and Fish, and the Object class is the superclass for Animal and all other Java classes. Note that the UML does not repeat a description of all the attributes and methods derived from the superclass. When an attribute from a parent or super class will be modified, the UML will repeat this description. The UML will also describe any new behaviors or attributes that are added to the subclass.

The symbol is introduced in this UML. This symbol represents the access modifier protected. The protected access modifier allows all the subclasses and other classes in the same package to access the method or variable. In this example, the walk() and eat() methods are protected. This allows the subclasses access to these methods, but not classes in other packages.

Abstraction

The same Animal class can also be used to derive a Spider class. This new class does not have a name attribute like the Fish or Cat classes. However, all of these classes share some similar behaviors. This similarity of behaviors and attributes allows the programmer to define a class with these common behaviors and derive the subclasses Cat Spider and Fish definitions from class Animal. This is shown in Figure 1. The Animal class generalizes the behaviors of many subclasses.

Often classes that define generalized behaviors such as the Animal class have little use as standalone classes. In any context, objects of the type Animal, a very general parent class, provide very little functionality. The Animal class could not provide the functionality needed for a Fish object or the functionality needed for a Cat object. This class is an abstract representation of the classes that inherit from it. The placing of common behaviors in an abstract class is another design feature of inheritance. The Fish, Cat and Spider classes represent concrete classes from which a useful object can be created.

Programmers arrive at abstract and concrete designs of classes in one of two ways. The first way is generalization, or discovery of general behaviors among classes. The second way is specialization, or the identification of specific adaptation of general behaviors or adoption of new behaviors in an inherited class.

When designing classes, common fields and behaviors lead to generalizations about the classes. These generalizations can be implemented through the design of parent classes, which are also known as superclasses. Superclasses can then be designed to describe required and optional fields and behaviors. A superclass can be an abstract representation of common behaviors and data. When a superclass is an abstract representation, the superclass cannot be used to create any objects. Objects demonstrate behaviors of an abstract superclass through concrete implementations of these behaviors in subclasses.

The Animal class can define common behaviors for Fish, Cat, and Spider objects. An object of the Animal class has almost no practical use. What a programmer uses is a specific instance of one of the derived classes. In object-oriented programming, the term concrete applies to a class from which an object can be created and used.

The term abstract is applied to classes from which no objects are expected to be created. In a program that manages data for an aquarium, the Fish class is derived as a concrete implementation of the Animal class. In a veterinarian application, the Cat object is a concrete implementation of the Animal class. In this manner, an abstract representation such as the Animal class can be used in two unrelated applications. This is shown in Figure . //e ca fig.1

Generalizations of classes into a superclass can be either concrete or abstract. For example, an application can design classes to include an Employee class and two derived classes called Manager and Programmer. Scroll down the graphic in Figure 3 to see the details for the Manager and Programmer classes. In this example, managers are represented using objects of the Manager class and programmers are represented using objects of the Programmer class. All other employees are represented using objects of the Employee class. All of the classes in the inheritance hierarchy are concrete classes. It is not unreasonable to expect to have objects of the type Employee without any additional information described in the class. This is an example of a parent class and derived classes that are all concrete classes and can be used to create objects. This means that each class can be used to create objects of the class. In this model, an object referenced by e1 is an instance of the Employee class. An object referenced by m1 is a instance of the Manager class and contains attributes and methods of the Employee class. This object "is a" Manager and "is an" Employee. Similarly an object referenced by p1 is a Programmer and an Employee.

While fish, cats, and spiders are all animals, their anatomy and behaviors are different. Fish swim and have fins instead of legs. Spiders have eight legs and cats only have four. These differences between fish, cats, and spiders represent specializations of the general and abstract class Animal. Fish, Cat, and Spider classes are subclasses of the parent superclass Animal. In the same sense, Manager and Programmer are subclasses of the parent class Employee

A subclass definition can include a method described in the parent class. The context in which this occurs is known as over-riding. This context suggests that the subclass version of a behavior is different than the parent class version of the behavior. Rules for overriding methods of a parent class are discussed in a later section. Some parent class methods must be overridden, in order to establish the subclass as a concrete class from which objects can be created. A parent class can hold general behaviors as in the example of the Animal class. However, in order to declare the class as an abstraction at least one method of the class must be defined as abstract and the class must be defined as abstract. When a subclass derives from a parent class that has been declared abstract, the subclass must override all methods that are declared abstract in the superclass, or the subclass itself must be abstract.

There are some important ideas regarding the abstract or concrete status of a class. A superclass can be either abstract or concrete. A subclass can also be abstract or concrete. A subclass can be derived from an abstract parent class and continue to add new methods or attributes without overriding the parent class abstract methods. In this case, the subclass is also declared abstract and no objects can be created of this class. In order to make the subclass concrete, all abstract methods of the parent class must be overridden.

The problem of multiple inheritance

In some object-oriented languages such as C++, a class can be derived from multiple parent classes or superclasses. In Java, a class may not have multiple superclasses. For example, if a Programmer object was both a member of the Person and Employee classes, and if both the Person and Employee classes have a field name and a method getName(), the JVM would not know which getName() method to use for a Programmer object. This is shown in Figure

To avoid such confusion, and because Java is a strongly typed language, a class can only derive from one parent class. A form of multiple inheritance is provided through the use of interfaces. These are described later in this module.

Inheritance hierarchies show the relationship between classes. It can show that the Programmer class is a subclass of the Employee class, which is a subclass of the Person class. In the same regards, it shows that the Person class is a superclass to the Employee class, the Programmer class, and all other classes that are subclasses of the Employee class or the Programmer class.

Figure 2 illustrates the four level hierarchy path for the TextField class, which is used in a GUI. GUIs include items such as windows and dialog boxes to facilitate user input. They are a vital aspect of virtually all applications.

Figure 3 shows the API class documentation for a class. Note that all API documentation presents the inheritance hierarchy for each class. Also notice that the class definition statement includes the declaration that the TextField class extends TextComponent. The keyword extends is used to declare an inheritance relationship between the classes.

In Figure 4, the API documentation shows all the methods inherited from the parent class.

Java Language Support for Inheritance

Java language keywords in inheritance

The Java language includes specific keywords that support inheritance. The most important is the keyword extends. When a class extends from another class, it is considered a subclass. Extending from another class is also known as subclassing. The idea behind keyword extends is that the child class definition includes all of the non-private attributes and behaviors of the parent class and adds its own unique attributes and behaviors.

Another keyword used with inheritance is super, which allows programmers to access constructors and overridden methods of a parent class. Since Java does not permit multiple inheritances, there is only one parent class. The keyword super provides a reference to the derived attributes of the object. The keyword super cannot access private features or circumvent access rules.

Object class

The Java language provides comprehensive support for inheritance through the API of classes. Almost any Java program that creates and uses GUIs, uses inheritance models that are implemented in the classes that form the Abstract Window Toolkit (AWT) of classes. Windows is an example of a operating system that creates and uses GUIs.

Each class that has been created extends from the Object class, which is the superclass of all classes. The table in Figure 1 shows all of the methods of the Object class.

All the attributes and behaviors of an object are defined by its class, its superclass, and the superclasses of the superclasses. Since the Object class is the superclass of all classes in Java, the attributes and behaviors defined in Object are present in all Java objects. As a result, Object class behaviors and attributes are inherited by all new classes.

The common Object ancestor of all classes allows the programmer to have a generic reference to any class, both API or user written. It is common for a methods to have an argument that states methodX(Object obj). This type of declaration suggests that the method will accept a reference to any type of object.

Each class that is created includes all of the methods of the Object class. Although every class extends the Object class, this information never has to be declared in the class definition. It is assumed that the class Animal or Employee extends the class Object, and therefore does not have to be declared.

Every class is a descendent of the Object class. When a custom class is created without extending from a parent class, the Java platform implicitly includes an "extends java.lang.Object" as part of the class definition. In this way, all classes extend from Object, either directly or indirectly through the hierarchy of the parent class. In the example of Animal, Cat and Fish, the Animal class derives directly from the Object class, and the Cat and Fish classes derive indirectly through their parent class, from the Object class.

Some methods of the Object class require special consideration. These are the equals() and toString() methods. These methods perform very generic actions when executed. For example, the equals() method will compare its reference value to that of another object. This is a comparison of the addresses of two objects and not the data. The toString() method will convert the reference value of an object to a String. Either of these methods may not be very useful when comparing or printing object data. In a later section the ways of overriding to change the operations of these methods will be explored.

In Figure , all of the derived methods of the Programmer class from the parent class Employee are identified. Note that all the derived methods from the Object class are also identified.

Access Modifiers and Inheritance

Role of access modifiers in inheritance

Access modifiers control what superclass attributes and methods are inherited by the subclass. Figure describes access modifiers and their impact on inheritance. The modifiers of the parent determine if a subclass can directly access parent class variables and methods and override parent class methods. These are the implications of the use of different modifiers:

  • private - A subclass cannot access these variables and methods, thus the subclass cannot override these methods. No other class can access these either.
  • protected - A subclass can be created in the package that the parent class belongs to or in a different package. The protected modifier allows the subclass to access any protected attribute or method, and to override any protected method. Additionally, classes in the same package as the parent class can access the protected method and attribute.

Default access is when no access modifier is used. In this state, the parent class attributes can be accessed by subclasses in the same package. Although methods can be overridden in subclasses of the same or different packages, the attribute cannot be accessed by the subclass in a different package.

Figure 2 shows the impact of inheritance when a subclass is in the same package as the parent class and when the subclass is in a different package. It is important to understand that all methods and data from a parent class exist in the subclass object. However, the private attributes and methods are inaccessible to the subclass object.

The code examples shown in Figure 3 include three classes, which are the Parent class, the Child class, and a Test class. A private attribute in the Parent class is not directly accessible to the subclass. The non-private method of the Parent class is directly accessible. The non-private method accesses the private attribute. This code shows that inaccessibility does not mean that the private methods and data do not exist. Note that the Child class makes a call to the Parent class getX() method and the public variable Y directly. Both of these are part of the inherited properties from the Parent class.

1 /**

2 * Java Program: Parent.java

3 * @author Cisco Teacher

4 * @version 2002

5 */

6 public class Parent

18

19 /**

20 * @return The new number as an int

21 */

22 public int getX()

26 }

1 /**

2 * Java Program: Child.java

3 * @author Cisco Teacher

4 * @version 2002

5 */

6 public class Child extends Parent

18 /* the private variable X of the parent is inherited,

although not directly accessible. The getX method of the parent class is public and inherited. It is used to access the parent class value. */

24 public void setX()

30 } // end class

Review the code of the Test class 4. Note that the Child object c is used to directly access the method getX() from the Parent class. Both of these examples show that all non-private attributes of a parent class are inherited and directly accessible.

If a subclass declares an attribute with the same name as an attribute of the superclass, a duplicate or shadow attribute is created. Avoid doing this unless it is an OO design requirement. This introduces uncertainty into the behavior of the classes. If another programmer uses these classes and expects the values of attributes in the parent class but receives the values of the shadow variables in the child class, their code may not work properly.

If a subclass declares a method with the same name, return-type, and argument as a parent class method, this is known as overriding. If the parent class declares a method to be final, this method cannot be overridden. If the parent class declares a method to be static this method cannot be overridden in the child class. When a child class overrides a parent class method, the child class can access the parent class method with the keyword super

Overriding

Method overriding

While inheritance provides extensive support to reuse existing classes, many of the methods of a superclass may need customizing. For example, the Object class methods equals() and toString() have limited uses if they only compare or print the addresses of objects. A toString()method that prints the data of an object in a formatted manner or an equals() method that compares the values of two objects, would be more practical. The ability of a programmer to redefine or customize the definition of a parent class method is known as overriding. This is another component of inheritance. Almost any method that is inherited can be overridden. The exception is a non-private method that has been declared final in the parent class. Recall that access modifiers influence inheritance. Only methods that are accessible can be overridden. The table in Figure 1 describes the rules for overriding parent class methods.

In the Animal class example, all of the subclasses of animals implement the eat() method in different ways. Therefore, the eat method has been overridden in each of the subclasses. Both the Spider and Cat objects use the walk method defined in the Animal class, which describes how many legs are used to walk. Since Fish do not walk, a class which represent them does not need a walk method. This method can be overridden in the Fish class to reflect this situation. Figure 2 illustrates the Animal class methods that have been overridden in each of the subclasses.

Fig.1

Fig.2

Overriding of object class methods

In general, class designs should include overriding the equals( hashCode(), and toString() methods. Apply this to the Student class used in previous examples. This is shown in Figure

1 /** * Student Class establishes the student id, name and grade

2 * @author Cisco Teacher

3 * @version 2002

4 */

5 public class Student

42

43 // Print student name and grade

44 public void printData()

76

77 // set student's id

78 /**

79 * @param id The student's id as an int

80 */

81 public void setStudentID(int id)

85

86 // get student's id

87 /**

88 * @return The student's id as an int

89 */ public int getStudentID()

System.out.println('Student name is: ' + studentName + ' Grade is: ' + grade);

48 }

49

50 // get student's name

51 /**

52 * @return The student's name as a String

53 */

54 public String getStudentName()

59 // set student's grade

60 /**

61 * @param newGrade The student's new grade as a String

62 */

63 public void setGrade(String newGrade)

68 // get student's grade

69 /**

70 * @return The student's grade as a String

71 */

72 public String getGrade()

System.out.println(s1); //prints the address of the object

106 }

107 }// End of Student class

It may be necessary for a class to override the following Object methods. The equals/hashCode are listed together since they must be overridden together.

  • clone
  • equals/hashCode
  • finalize
  • toString
  • A class cannot override these Object methods, since they are final:
  • getClass
  • notify
  • notifyAll
  • wait

The Student class has methods to access private data. The Student class inherits the equals() method and the toString() method from the Object class. Using these methods with Student objects produces information that is not useable. For example, both Student objects contain the same data. However, each Student object has a different address and causes the method to return false.

The System.out.println() method will use the toString()method of an object to print information about the object. Since the toString() method in the Object class only returns the memory address of the object as a String, this is what is printed.

To deal with these limitations, override the toString(), equals(), and the hashCode() methods in the Student class. The System.out class uses the toString() method of an object to print information about the object. The Student version of the toString() method will return a String that represents the student name, identification, and other information. When the System.out.println() method is provided a reference to the Student object, it uses the overridden toString() method to print student information that is useful. This is shown in Figure .

1 /**

2 * Student Class establishes the student id, name and grade

3 * @author Cisco Teacher

4 * @version 2002

5 */

6 public class Student

59

60 // set student's grade

61 /**

62 * @param newGrade The student's new grade as a String

63 */

64 public void setGrade(String newGrade)

69 // get student's grade

70 /**

71 * @return The student's grade as a String

72 */

73 public String getGrade()

77

78 // set student's id

79 /**

80 * @param id The student's id as an int

81 */

82 public void setStudentID(int id)

37 public Student(String name, String grd, int id)

43

44 // Print student name and grade

45 public void printData()

50

51 // get student's name

52 /**

53 * @return The student's name as a String

54 */

55 public String getStudentName()

95

96 // overridden toString method

97 public String toString()

104 // Main method

105 public static void main(String[] args)

System.out.println(s1);

116 }

117 }// End of Student class

Since two Student objects will need to be compared to ensure that none of the student information is duplicated, the equals() method is overridden. It is possible for two Student objects to have the same data, but since they are not the same object, they will have different memory addresses. The address of an object is calculated using a hashing algorithm, which is a unique identifier given to each object on the heap. The hashing algorithm is in the code of the hashCode() method and is used to generate a unique value known as the hash value for the object. To ensure that this unique identifier is the same, the hashCode() method of the object needs to be overridden. In this example, the hashCode()method uses the student identification to determine a hash value. The method returns an integer as the hash value of the object. The equals()method is overridden to compare the data in the fields of the two objects. If all fields are equal, then the method returns a true. A test of the hash value of the objects is also included.

In Figure 3, the equals() method is overridden, but not the hashCode() method. Although the objects contain the same data, since each one has been assigned a different hash value they will be considered different objects.

3 viewkind4uc1pardf0fs20

/** par

4 * Student Class establishes the student id, name and gradepar

5 * @author Cisco Teacherpar

6 * @version 2002par

7 */ par

8 public class Studentpar

9 par

19 // constructor with 2 argumentspar

20 /**par

21 * @param name The student's name as a Stringpar

System.out.println('Student name is: ' + studentName +par ' Grade is: ' + grade);par

47 }par

48 // get student's namepar

49 /**par

50 * @return The student's name as a Stringpar

51 */par

52 public String getStudentName()par

53 par

56 // set student's gradepar

57 /**par

58 * @param newGrade The student's new grade as a Stringpar

59 */par

60 public void setGrade(String newGrade)par

61 par

64 // get student's gradepar

65 /**par

66 * @return The student's grade as a Stringpar

67 */par

68 public String getGrade()par

69 par

72 // set student's idpar

73 /**par

74 * @param id The student's id as an intpar

75 */par

76 public void setStudentID(int id)par

77 par

80 // get student's idpar

81 /**par

82 * @return The student's id as an intpar

83 */par

84 public int getStudentID()par

85 par

22 * @param grd The student's grade as a Stringpar

23 */par

24 public Student(String name, String grd)par

25 par

30 // constructor with 3 argumentspar

31 /**par

32 * @param name The student's name as a Stringpar

33 * @param grd The student's grade as a Stringpar

34 * @param id The student's id as an intpar

35 */par

36 public Student(String name, String grd, int id)par

37 par

42 // Print student name and gradepar

43 public void printData()par

44 par

95 // overridden equals methodpar

96 /**par

97 * @param s A student as a Student data typepar

98 */par

99 public boolean equals(Student s)par

100 par

return test;par

109 }par

110 // Main methodpar

111 public static void main(String[] args)par

112 par

System.out.println(s1);par

System.out.println(s1);par

122 }par

123 }// End of Student classpar

In Figure 4, the hashCode() and the equals() methods are both overridden. This yields a more accurate result of the comparison of the two objects.

3 viewkind4uc1pardf0fs20 /**par

4 * Student Class establishes the student id, name and gradepar

5 * @author Cisco Teacherpar

14 // null constructorpar

15 public Student( )par

16 par

19 // constructor with 2 argumentspar

20 /**par

21 * @param name The student's name as a Stringpar

22 * @param grd The student's grade as a Stringpar

23 */par

24 public Student(String name, String grd)par

25 par

30 // constructor with 3 argumentspar

31 /**par

32 * @param name The student's name as a Stringpar

33 * @param grd The student's grade as a Stringpar

34 * @param id The student's id as an intpar

35 */par

36 public Student(String name, String grd, int id)par

37 par

42 // Print student name and gradepar

43 public void printData()par

44 par

48 // get student's namepar

49 /**par

50 * @return The student's name as a Stringpar

51 */par

52 public String getStudentName()par

53 par

56 // set student's gradepar

57 /**par

58 * @param newGrade The student's new grade as a Stringpar

59 */par

60 public void setGrade(String newGrade)par

61 par

64 // get student's gradepar

65 /**par

66 * @return The student's grade as a Stringpar

67 */par

68 public String getGrade()par

69 par

6 * @version 2002par

7 */par

8 public class Studentpar

9 {par

10 private final String studentName;par

11 private String grade;par

12 private int studentID;par

13 public static final int courseNumber = 12345;par

72 // set student's idpar

73 /**par

74 * @param id The student's id as an intpar

75 */par

76 public void setStudentID(int id)par

77 par

80 // get student's idpar

81 /**par

82 * @return The student's id as an intpar

83 */par

84 public int getStudentID()par

85 par

88 // overridden toString methodpar

89 public String toString()par

90 par

95 par

96 // overridden equals methodpar

97 /**par

98 * @param s A student as a Student data typepar

99 */par

100 public boolean equals(Student s)par

101 par

return test;par

110 }par

111 //overridden hashCode methodpar

112 /**par

113 * @return The student's info as an intpar

114 */par

115 public int hashCode()par

116 par

120 // Main methodpar

121 public static void main(String[] args)par

122 par

System.out.println(s1);par

System.out.println(s1);par

132 }par

133 }// End of Student classpar

Overloading versus overriding

The figure presents a comparison of overloading and overriding techniques. Both can be used in classes that form an inheritance hierarchy.

Use of this and super

Access parent and subclass methods and data

A subclass should be viewed as incorporating all the methods and attributes of its hierarchy of parents. The figure illustrates the subclass SportsCoupe and the parent class BaseModelAuto. To reference the methods and data of each object, it is possible to use the variables this and super in the methods. All of the methods of the subclass include the this variable and the super variable. The this variable contains a reference to the subclass object. The super variable contains a reference to the parent object.

The use of super is not required for attributes and methods that have not been overridden by the subclass.

In the sample code, this and super are used in two places. The parent class method is overridden in the subclass. The overridden method calls the parent class method using the super variable. The overloaded method uses the this variable to call the method of the parent class that is overridden in this subclass.

To add more functionality to a parent class method, instead of completely overriding the method, call the overridden method using the super keyword. For example, the getAccessories method in the subclass SportsCoupe added functionality to the getAccessories method in the superclass BaseModelAuto with the code on lines 15 through 1

2 * Java Program: SportsCoupe.java

3 * @author Cisco Teacher

4 * @version 2002

5 */

6 public class SportsCoupe extends BaseModelAuto

19

20 /**

* @param options The car's options as a String

22 * @return The car's accessories as a String

23 */

24 public String getAccessories(String options)

28 //additional methods

29

30 public static void main(String[] args)

38 } // end of SportsCoupe class

2 * Java Program: BaseModelAuto.java

3 * @author Cisco Teacher

4 * @version 2002

5 */

6 public class BaseModelAuto

7

20

21 //additional methods

22 } // end of BaseModelAuto class

Inheritance and Constructors

Handling constructors in inheritance

Inheritance makes non-private code and data defined in the parent class accessible to the subclass. The only exception is constructors. Constructors are not inherited in the normal way, even if they are non-private. Constructors must be defined for each subclass. Figure shows the use of the new operator to construct an object and the matching constructor that is used. In this example, the code for MyClass includes overloaded constructors. Overloading means different versions of the same method exist in the same class.

1 /** * Java Program: MyClass.java

2 * @author Cisco Teacher

3 * @version 2002

4 */

5

6 public class MyClass

8 private int studentID;

9 private int creditHoursEarned;

10 private double tuitionBalance;

11 private String studentName;

12 private String studentAddress;

13

14 //Overloaded Constructors, demonstrating 'name mangling'

15 public MyClass()

18

19 /**

20 * @param id The student's id as an int

21 */

22 public MyClass(int id)

26

27 /**

28 * @param id The student's id as an int

29 * @param credit The student's credits as an int

30 */

31 public MyClass(int id, int credits)

36

37 /**

38 * @param id The student's id as an int

39 * @param balance The student's balance as a double

81 /**

82 * @param id The student's id as an int

83 * @param name The student's name as a String

84 * @param balance The student's balance as a double

85 */

86 public MyClass(int id, String name, double balance)

40 */

41 public MyClass(int id, double balance)

47 /**

48 * @param id The student's id as an int

49 * @param name The student's name as a String

50 */

51 public MyClass(int id, String name)

57 /**

58 * @param id The student's id as an int

59 * @param address The student's address as a String

60 */

61 // causes compilation error since MyClass constructor with (int, String)

62 // already defined

63 public MyClass(int id, String address)

69 /**

70 * @param address The student's address as a String

71 * @param id The student's id as an int

72 */

73 // Could reverse arguments since (String, int)

74 // pattern has not been used

75 public MyClass(String address, int id)

93 //Additional methods

95 public static void main(String[] args)

104 } // end of MyClass class

The keyword extends means that an object of the parent class is constructed and then extended to include the data and methods of the subclass. The creation of objects in an inheritance model is far more complex than the creation of objects with the Object parent class. This is shown in Figure 2.

 

When the inheritance model is applied to a class definition, a number of rules apply that affect the inclusion of constructors in the child class. In order to understand these rules, it is important to recognize that a child class object contains within it the attributes of its parent classes, all the way up to the level of the Object class. When an object of the child class is created, all the attributes of its parent class are created first, and then the attributes of the child class. Recall the steps by which an object is created. When the new operator is invoked, memory is allocated to all the attributes of the object, and the default values are assigned. Explicit initialization occurs and then the code of the constructor is executed.

After all the attributes of the subclass and parent class of the object have been initialized, then the constructors for each of the classes are executed. This always begins with the execution of the parent class constructor. Since the parent class attributes are created first, the corresponding constructor for this class is executed to complete the parent portion of the object.

Since the first constructor call in the child class constructor is a call to the parent class constructor, a number of situations exist regarding the inclusion of constructors in the parent and child class:

  • If the parent class uses the default constructor, then the child class can also use the default constructor. Recall that the default constructor is inserted by the compiler if none is provided. In the case of derived or subclasses, the compiler will insert a default constructor in the child class and it will also insert the statement super(), which is a call to the parent class default constructor.
  • If the parent class explicitly includes a no-argument constructor, the child class can use the default constructor. When the compiler inserts the call super(), this code will compile, because a no-argument constructor has been explicitly coded in the parent class.
  • When a parent class does not include a no-argument constructor, the child class cannot use the default constructor. When the compiler tries to insert the call super(), it will fail since this call is not valid for the parent class.
  • Each constructor that is included in a subclass must include a call to the parent constructor. If a cascading call to several constructors is used, the constructor that will finally execute must have the call to the parent constructor as the very first statement.

Figure 3 identifies the different conditions for using constructors from subclasses and superclasses. The call to a parent constructor is through the use of the keyword super. The format of the statement is to match at least one argument list of a constructor of the parent class. The name for the parent class is not used in this call. Since Java does not permit multiple inheritance, there can only be one parent to any subclass. The variable super has a reference to the parent class object and its definition.

The sample code in Figures 4 and demonstrates the correct and incorrect usage of the keyword super and constructors in the construction of a subclass.

1 class Parent

10

11 // some methods

12 }

13

14 class Child extends Parent

1 class Parent

10

11 // some methods

12 }

13

14 class Child extends Parent

21 // OTHER METHODS

22 }

The Child class in Figure will not compile. The compiler will try to insert a null constructor and an implicit call to super(). Note that the Parent class does not have a null constructor. This is because the Parent class has an explicitly defined constructor. The Child class in Figure will compile. The null constructor of the Child class has been overridden to call the Parent constructor, using super and passing the argument required by the Parent constructor.

Constructors in subclasses can be overloaded. The example in Figure 6 illustrates the use of overloaded constructors that call the super constructor.

2 * Java Program Person.java

3 * @author Cisco Teacher

4 * @version 2002

5 */

6 public class Person

12

13 // some methods

14 }

16 /**

17 * Java Program: Student.java

18 * @author Cisco Teacher

19 * @version 2002

20 */

21 class Student extends Person

40 // constructor with two argument

41 /**

42 * @param name The student's name as a String

43 * @param grd The student's grade as a String

44 */

45 Student(String name, String grd)

51

52 // constructor with one argument

53 /**

54 * @param name The student's name as a String

55 */

56 Student(String name)

60 // OTHER METHODS

61 }

Extending Classes

Abstract classes

As a programmer moves up the inheritance hierarchy, classes become more general and often more abstract. At some point, the ancestor class becomes so general that it becomes a guideline for other classes, rather than a definition for an object that can be used. When a class in a hierarchy serves as a framework or guideline for other classes, the class is defined as abstract. In this case, the class is not expected to be used to create objects that store data and do work. The class is used to set boundaries for definitions of other subclasses. It is viewed as a common framework for a set of related subclasses.

Consider an electronic messaging system, such as fax, e-mail, voicemail, and postal mail. The common feature of all the messaging classes is having a message. An inheritance hierarchy is shown in Figure 1. A Message object must have information on how a message will be transported. Thus, the Message class serves as an abstract framework for all of the other subclasses.

The ultimate goal of OO design is to factor out the common operations and data to a higher level in the inheritance hierarchy. As the common operations are factored out, it may become clear that the details of how the operations are implemented cannot be specified in a higher-level class. For example, in the message system, the display() method can be implemented in all of the subclasses. How is this implemented for the Message class? Clearly the method display() is an abstract concept. It is a framework to define inclusion of such a method in the subclass definitions. An abstract method is declared using the syntax shown in Figure . An abstract method does not have any body of code. A class that has an abstract method must be declared abstract

1 /*

2 An abstract method is declared using the following syntax:

3

4 abstract method-name (arguments);

5

6 An abstract method does not have any body of code.

7 A class that has an abstract method must be declared abstract.

8

9 abstract class ClassName

10

11 */

13 public abstract class AbstractDemo//end AbstractDemo

The sample code shown in Figure 3 presents the Message class definition, including the abstract display method.

2 * Java Program: Message.java

3 * @author Cisco Teacher

4 * @version 2002

5 */

6 abstract class Message

23

24 // abstract display method

25 abstract void display()

26

27 // other methods

28

29 } // end class

Figure 4 sets out the guidelines for the creation of abstract classes. In the case of the messaging system, the abstract class Message can store sender, receiver, and subject information as data values. These are concrete data. Programmers of many GUI classes use the abstract class design to move as many common methods and data into the superclass as possible.

Final classes

The keyword final was introduced in the definition of data values as constants. The keyword final always indicates that the object, method, or data cannot be changed. In inheritance models, the keyword final, when applied to the methods of a class, prevents the method from being overridden by any subclass.

The keyword final, when applied to a class definition, prevents a class from being used as a superclass to derive subclasses. This class cannot be extended. There are several classes in the Java language that have been declared final. One of the most commonly used is the String class. This is shown in Figure 1. A programmer does not expect to have this class extended to some other unpredictable extension of the String class. If a class must be used in a controlled manner, declare the class to be final

The wrapper classes, which wrap object methods around Java primitives, are also declared final and cannot be extended. This is shown in Figure 2.

Interfaces

What and why of interfaces

As stated earlier, Java does not allow for multiple inheritance.

Consider a Programmer class. This class represents individuals who are part of the Employee group of an organization. If a Programmer has to be represented as a Spouse in one context, an Employee in another, and a Programmer in yet another, Java would not enable this through inheritance. A Programmer class cannot extend from both a Spouse class and an Employee class, even though a programmer could be both a Spouse and an Employee. If a programmer is described as both a Spouse and an Employee, this generally refers to the operations or behaviors that are associated with these classes. While all the data pertinent to a programmer could reside in either the parent class Spouse or the parent class Employee, it should be possible to represent a Programmer as a Spouse in some contexts and as an Employee in others.

This requires a way to create an object that holds data representing the Programmer class and can also perform operations associated with a different class of objects. The Java language provides an interface facility for implementing multiple inheritance, which is deriving behaviors from two unrelated classes. Interfaces enable multiple inheritance of behaviors from different classes and serve as a design document for external features of a class.

Interfaces are abstract classes that define abstract methods and constants. All of the methods in an interface must be public. An interface can include constants, but no other types of attributes. Interfaces provide a mechanism for a subclass to define behaviors from sources other than the direct and indirect superclasses.

Interfaces can be used to perform these tasks:

  • Capture similarities among unrelated classes without artificially forcing a class relationship
  • Declare methods that classes are expected to implement
  • Reveal the programming interface of an object without revealing its class

Consider the example of classes that describe things that fly. Flying includes actions such as taking off, landing, and flying. An interface can be created which defines all of theses actions in the form of abstract methods. Things that fly can include a bird, an airplane, and a helicopter. Each object takes off, lands, and flies differently. The bird flaps its wings, the airplane uses the thrust from an engine, and the helicopter utilizes a rotor blade. Each flying thing implements a different procedure for what seems to be common and similar actions. An interface such as the Flyer interface can define these common methods. Each of the classes implements this interface. Figure 1 shows the inheritance relationship between the Flyer interface and the classes.

In addition to implementing a Flyer interface, each of these objects is part of its own superclass/subclass hierarchy. Figure 2 illustrates how the classes relate to their inheritance hierarchies and to the interface implementations. In this example, one can agree that an Airplane is not an Animal and a Bird is not a Vehicle, but a Bird and an Airplane are both Flyer objects.

A class must implement all the methods that are declared in the interface or the class must be defined as abstract.

In the Animal inheritance hierarchy some of the subclasses, specifically the Fish and Cat classes, can be considered pets. These classes have common behaviors that relate to being a pet. A Pet interface could be added to the class design in order to address these common methods. Figure 3 illustrates the inheritance relationship between this new Pet interface and the other classes in the Animal inheritance hierarchy.

Object class

The syntax for implementing an interface includes the use of the keyword implements in the class definition statement. Implementing interfaces is more than the declaration in the class definition statement. This declaration is viewed as a contract between the class that implements the interface and the interface itself. The compiler enforces this contract by ensuring that all methods declared in the interface are also implemented in the class. In some cases, this may include a null implementation. A null implementation is an implementation of a method definition without any procedural code. For example, since fish do not play, a null method implementation is used to satisfy the contract between the Fish class and the Pet interface. This is shown in Figure

Methods declared in an interface are always public. The compiler will automatically insert the access modifier public. When an interface method is implemented in a class, it is a common error to use the default access modifier similar to the interface declaration. This will result in a compiler error since the default access modifier for a class method is default level access, also known as package access, which the compiler will identify as a weaker access level then the required public access.

Figure 2 summarizes the implementation of an interface.

Polymorphism, Dynamic Binding, and Virtual Method Invocation

Polymorphism

Polymorphism literally means 'many forms'. Polymorphism is a mechanism in the Java language that adds enormous flexibility to programs. To understand the concept of an object assuming many forms, review the code in Figure

Note that there are objects of one class being represented by reference variables that are of a different class. These statements are constructing objects that can be handled in different ways depending on the reference type. The second row in the table shows some objects that are created. In the first statement, the object is actually a Bird. The object will have all the attributes of the Bird class and the Animal class. In this statement, the reference to the object is through the variable of the type Animal. This statement to means that the object Bird, in this context will be seen only in the form of the Animal. The only behaviors and attributes accessible will that of the Animal part of the object.

In the second statement, the object created is an Eagle and the reference to the object is of the type Flyer. In this context, the object will take on the form of the Flyer and the behaviors of the Flyer are all accessible through the reference variable. Each of these statements shows that although an object is of a particular type, the form it takes is based on the reference type used to access the object.

The third row illustrates another perspective of polymorphism. In this row, the objects created in the first row are cast in a different form. For example the first statement casts the Bird object as its true form bird. The object is seen as a bird and in the second row, this same object is referenced as an Animal. Observe that any object can be referenced by any of the forms that the class implements or inherits. The object Bird can be seen as an Animal, a Bird, or a Flyer

In general terms, polymorphism allows the same code to have different effects at run-time depending on the context. Polymorphism takes advantage of inheritance and interface implementations. Polymorphism is best understood in the context of code. In Figure , polymorphism is used in object creation.

In this example, assume the Employee class and the Teacher class both have a method getDetails(). The code for each one is different. The Employee class getDetails() method returns a String that contains the identification and name of each employee. The TeachergetDetails() method returns an identification, name, classroom, and grade. If e1.getDetails() and t1.getDetails() are called, different behaviors are exhibited and different results are returned. It is not obvious what happens with e2. The object referenced by e2 is an example of polymorphism. Here the variable e2 is of the type Employee. The actual object created and resulting object reference assigned to e2 is a Teacher object. At run-time, the e2.getDetails() will result in the invocation of the getDetails() method of the Teacher object. This is known as dynamic method invocation or virtual method binding. The method that is executed is the method of the object, and not the method of the class of the reference variable.

Another contextual use of the polymorphism concept is in the context of method calls. In Figure 4, the School class has a method display(Employee e). This method accepts objects of the type Employee. In the call to this method, line 37 passes the reference to an Employee object and line 38 passes a reference to a Teacher object. This works in this statement because a Teacher is an Employee. Line 39 passes the variable e2, which is of the type Employee, but holds a reference to a Teacher object.

1 /**

2 * This class uses Employee and Teacher objects

3 * @author Cisco Teacher

4 * @version 2002

5 */

6 public class School

16

17 /**

18 * @param t The Teacher object

19 */

20 public String setClassroom(Teacher t)

24

25 public static void main(String args [])

56

57 } // end of School class

The class named School has a method setClassroom(Teacher t). This method accepts references to objects of the type Teacher. Line 41 will work because t1 references a Teacher object. Line 47 will not work. While a Teacher is an Employee, not all employees are Teachers. As a result, the Employee object is not always a Teacher object. Inheritance only works in one direction, from superclass to subclass. A method that receives an object of a type can be called with objects that are subclasses of that type, but not more general or superclasses of the type. Line 54 works because it holds a reference to a Teacher object, even though the variable e2 is of the type Employee

Another way objects work together is by defining methods that take other objects as parameters. More cooperation and efficiency occurs when the objects are united by a common superclass. All classes in the Java programming language have an inheritance relationship. For example, a method that is defined to take java.lang.Object as a parameter can accept any object in the Java platform. This form of cooperation is called polymorphism.

Virtual method invocation or dynamic method binding

The technique of resolving the behaviors of an object at run-time is known as dynamic method binding, or virtual method invocation. This is a key feature of polymorphism. In the code for the School class, line 29 will create a variable that is a reference of the type Employee. However, at runtime, the call to the e2.getDetails() on line 35 will invoke the method of the Teacher class. This is because on line 29, the object that was created is a Teacher object.

Dynamic binding resolves which method to call at run-time when more than one class in an inheritance hierarchy has implemented the method. The JVM looks at the type of object for which the call is made, not the type of object reference in the calling statement. So in line 29, e2 is a reference of the type Employee in the calling statement, but the object being called is a Teacher object. Therefore, the Teacher version of the getDetails()method is used.

Dynamic binding also resolves the handling of the arguments being passed to a method. Again, the JVM looks at the type of object being passed by value as an argument, not the reference type of the variable being passed as an argument to the method. In line 54, the method argument e2 is a reference variable of the type Employee. However, the object actually being referenced is a Teacher object and the method setClassroom(), which requires a Teacher argument, is successfully invoked.

2 * This class uses Employee and Teacher objects

3 * @author Cisco Teacher

4 * @version 2002

5 */

6 public class School

7

16

17 /**

18 * @param t The Teacher object

19 */

20 public String setClassroom(Teacher t)

24

25 public static void main(String args [])

56

57 } // end of School class



Politica de confidentialitate | Termeni si conditii de utilizare



DISTRIBUIE DOCUMENTUL

Comentarii


Vizualizari: 1424
Importanta: rank

Comenteaza documentul:

Te rugam sa te autentifici sau sa iti faci cont pentru a putea comenta

Creaza cont nou

Termeni si conditii de utilizare | Contact
© SCRIGROUP 2024 . All rights reserved