CATEGORII DOCUMENTE |
Asp | Autocad | C | Dot net | Excel | Fox pro | Html | Java |
Linux | Mathcad | Photoshop | Php | Sql | Visual studio | Windows | Xml |
|
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:
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:
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.
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:
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:
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 |
Vizualizari: 1539
Importanta:
Termeni si conditii de utilizare | Contact
© SCRIGROUP 2024 . All rights reserved