Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Concept: Inheritance Definition: Inheritance in Java is the ability to create classes that inherit behavior and state from a “parent” class. These classes provide additional specialization, either in state or behavior, than the parent class does. The inheritance relationship can be thought of as the “is-a” relationship. • Superclass - more general class that provides common state and/or behavior to the classes that inherit from it. • Subclass - class that uses the behavior inherited from the superclass to provide some specialized and more specific behavior, often adding additional behaviors and/or attributes to implement that specialization. All classes in Java inherit, either directly or indirectly, from the Object class. If a class definition does not specifically inherit from, or extend, another class, it implicitly extends the Object class. Thus, every class in Java defines a type that also is-a Object. Hierarchies of Type: There are many examples of hierarchical types. One example is the taxonomic hierarchy scientists use to classify living things, shown in Figure 1 below. Each level of the hierarchy describes specializations of the level above, while still embodying the characteristics of the levels of the hierarchy on a path up the “tree.” Animalia Vertebra Amphibia Mammalia Carnivora Primates Insectovora Hominidae Gorilla Homo Pan Pongo Figure 1: Abbreviated hierarchy of the animal kingdom Figure 2 illustrates a part of the type hierarchy within the Java API. In this partial view, we can see that the Reader (java.io.Reader), Number (java.lang.Number), and Component (java.awt.Component) inherit directly from the Object (java.lang.Object) class. Each adds specific specialization to the very general Object class, tailoring the parent class to meet particular needs within the context of the API. If we compare, for example, the Number class with the Integer class, we can find 3 key differences that help minimize the confusion between the subclass and the superclass. • The keyword extends (found in the source code of the Integer class, as well as in the API documentation) suggests that the Integer class extends or adds to the Number class. Indeed, if we look at the documentation for the Number class, we find that it serves as the parent or super class for the BigDecimal, BigInteger, Byte, Double, Float, Integer, Long, and Short classes, all of which represent numeric types. • The Integer class adds additional fields to the Number class, allowing it to maintain a state that is characteristic of an integer value, differentiated from floating point and other numeric types. Object Reader Number Integer InputStreamReader FileReader Component Double BufferedReader Container Window Frame JFrame Figure 2: Examples of inheritance and type hierarchy in the Java API • The Integer class can do more - it has additional methods that further differentiate this class from other numeric types. Syntax: The primary syntactical element used to explicitly implement inheritance is the keyword extends. class SubclassName extends SuperclassName { // methods // fields } class Cell extends JTextField { public Cell ( int value , int row , int col ) { super ((1 > value || 9 < value ) ? " " : Integer . toString ( value )); this . row = row ; this . col = col ; setEditable (1 > value || 9 < value ); setFocusable (1 > value || 9 < value ); setVisible ( true ); } public int getRow () { return row ; } public int getColumn () { return col ; } public void setValue ( int val ) { setText ((0 == val ) ? " " : Integer . toString ( val )); } public int getIntValue () { try { return Integer . parseInt ( getText ()); } catch ( N umb erFo r mat Ex ce p ti on e ) { return 0; } } private int row , col ; } In Java GUI applications, it is common to create classes that extend the basic AWT and Swing components to provide specific behaviors. The example in the listing above illustrates such a specialization of the JTextField class. This particular specialization was developed for use in a Sudoku game as a data entry and display component in the GUI for the game. Note that it has significant added capabilities: it knows what row and column it occupies on the game board, and it knows that if it is created with a value between 1 and 9 (inclusive), the cell represents a “given” value that cannot be changed. Inheriting Instance Methods: When implementing an inheritance relation, you have three possible alternatives for defining methods: 1. You can override methods defined in the superclass by specifying a mathod in your class definition that has exactly the same signature (access specifier, return type, name, and parameters). When the method is applied to an object of the subclass type, the overriding method is invoked instead of the original method defined in the super class. 2. Methods can be inherited from the superclass. Methods not overridden in a subclass are inherited from the parent class. These methods may be called on any object of the subclass. 3. You can also define new methods, and usually will. This is the essence of using inheritance – you want to use an existing, common behavior as a foundation for a specialization of that behavior. Compare the API documentation for the Integer and Number classes. Inheriting Instance Fields: The main difference between inheriting fields and methods is that instance fields cannot be overridden. In general, there are only 2 cases for implementing fields in subclasses. 1. The subclass automatically inherits all instance fields from the superclass. 2. As with methods, any new fields declared in the subclass are present only in the subclass. Inheritance vs. Composition: Composition is a very basic, and generally data-centric, means of constructing classes of entities. Classes are built from aggregations of other objects, reusing their implementation within the composing class. The composition relation is often referred to as the “has-a” relation, indicating that each of the aggregated objects is a “part of ” the “whole” as represented by the composing class. For example, a Person “has-a” Name, or a Name “is a part of ” a Person. Inheritance, on the other hand, reuses the implementation of the parent superclass, inheriting state and behavior from it. Inheritance involves some kind of “specialization” of the superclass to tailor its behavior to a particular context. Thus, a Student “is-a” Person, although not all Persons are Students. Inheritance vs. Interfaces: Inheritance is similar to the implementation of an interface, except that interfaces do not have state or behavior. Also, interfaces are not classes, by definition, although inheritance relations can exist between interfaces (but not between an interface and a class, either way). Superclass Member Access: Subclasses have access to all public members of the superclass, but not to members (either fields or methods) that are declared private. If a subclass needs access to a private member of the superclass (generally, a field), it must use a method in the public interface of the superclass to access it. Another kind of superclass access relates to calling superclass methods that are overridden in the subclass. Consider the case of a “generic” BankAccount class: public class BankAccount { public BankAccount ( double initBal ) { balance = initBal ; } public void deposit ( double amt ) { balance = balance + amt ; } public void withdraw ( double amt ) { balance = balance - amt ; } public double getBalance () { return balance ; } private double balance ; } Note: this is a very simple bank account, with no overdraft protection at all! Now consider a checking account, still with the same simple bookkeeping, but with the stipulation that charges a fee for each withdrawal transaction over 10 in a statement period. The checking account is not charged with the responsibility for keeping track of time, only to count the number of transactions, and provide a means of calculating the service fee, given a fee per transaction. The implication of this behavior is that the withdraw method must be redefined, overriding the method in the BankAccount class. However, the superclass does not provide any way to set a balance, other than using the deposit and withdraw methods, and as a subclass, CheckingAccount cannot access the private data member “balance.” Also, if we override the withdraw method, but need to use the superclass version as well, there must be a means of differentiating between the two methods. The solution is to use a reference to the superclass, similar to the this reference to “this” object reference, called super. The listing below illustrates the use of super to access a method of the superclass within an overriding method in a subclass. public class CheckingAccount extends BankAccount { public CheckingAccount ( double initBal ) { super ( initBal ); transCount = 0; } public void withdraw ( double amt ) { transCount ++; super . withdraw ( amt ); } private int transCount ; } There are two other things to note in this example: • The first statement in the CheckingAccount constructor is a call to the constructor of the superclass. This is necessary because the superclass defines a constructor that takes an argument, and does not provide a default, or no-argument, constructor. This call must be the first statement in the constructor of a subclass. • The CheckingAccount class does not provide alternative implementations for the other 2 BankAccount classes (deposit and getBalance). These methods are inherited from the super class. Memory Allocation: The subclass “contains” all of the implementation (methods and fields) of the superclass. Figure 3 illustrates this in terms of the memory allocation of an object of the Cell class (listed above). Part of the object’s memory image contains the fields defined in the JTextField class, while another part contains the memory for the fields specifically declared within the Cell class. Cell text:String ... other fields JTextField portion row:int col:int Cell portion Figure 3: Memory allocation within a Cell object Subclass Constructors: A subclass constructor must initialize the superclass object within the subclass instance. This initialization may be done explicitly or implicitly. If the superclass has a ”default” constructor (e.g., one that has no parameters) explicit initialization is not required, as the compiler will use the default constructor to perform the task. If the superclass does not have a default constructor, an explicit call (with appropriate arguments) must be made to initialize the superclass. This is accomplished using the super keyword is used as a method name (see the CheckingAccount example above and the train car example below). public abstract class AbstractTrainCar { public AbstractTrainCar ( String id , int weight ) { idNumber = id ; emptyWeight = weight ; } public String getIDNumber () { return idNumber ; } public int getEmptyWeight () { return emptyWeight ; } public abstract int getTotalWeight (); private String idNumber ; private int emptyWeight ; } public abstract class FreightCar extends AbstractTrainCar public FreightCar ( String id , int weight ) { super ( id , weight ); freightWeight = 0; } public int getTotalWeight () { return getEmptyWeight () public void addFreight ( int weight ) { freightWeight += public void removeFreight ( int weight ) { freightWeight public boolean isHazardous () { return false ; } { + freightWeight ; } weight ; } -= weight ; } private int freightWeight ; } public class BoxCar extends FreightCar { public BoxCar ( String id , int weight ) { super ( id , weight ); hazardousCargo = false ; } public boolean isHazardous () { return hazardousCargo ; } public void setHazardous ( boolean haz ) { hazardousCargo = haz ; } private boolean hazardousCargo ; } Type Conversions: At different times, we may need to convert between types within a type hierarchy. These conversions will either be subclass to superclass, or superclass to subclass. • Subclass to Superclass Conversions - Since a subclass “is-a” specialization of a superclass, no extra effort is needed to convert a subclass reference to a superclass reference. BoxCar bcar = new BoxCar ( " 1234 D99 " , 23401); FreightCar fcar = bcar ; Object carObj = bcar ; • Superclass to Subclass Conversions - In this case, you are moving from a general type to a more specific type, e.g., increasing what you know about the referred-to object. There is a risk that the conversion is not allowed, so the compiler requires an explicit cast to perform the conversion. The situation is much the same as converting interface-type references to the class type implementing the interface. Java also provides an operator (instanceof) to allow the class type of a reference to be checked. The instanceof operator returns a true value if the object reference is an instance of the specified class and false otherwise. This allows a programmer to check the type of a reference before attempting an explicit type cast. if ( carObj instanceof BoxCar ) { BoxCar box = ( BoxCar ) carObj ; ... } Abstract Classes: Abstract classes are used when we need or want to force a programmer to extend a class. This may be because we cannot define all of the behaviors precisely, e.g., when some common behaviors must be defined in more specialized classes. The AbstractTrainCar class above is an example of this case. Note that the getTotalWeight() method is declared abstract, and that the method does not have a defined body (just like a interface method). This requires any class that extends AbstractTrainCar to either implement this method, or to be abstract itself. If a class has any method declared as abstract, the class itself must also be declared abstract as well. Another case where an abstract class can be effectively used is when a general, stereotypical definition of state and behavior can be made for a broad class of objects, but this stereotype does not normally exist as a distinct instance. Rather, the common state and behavior are embodied by the various specializations that do actually exist. The FreightCar class above is an example of this. All train cars that carry freight should be able to report the weight of the freight they are carrying, but the concept of a freight car is not one that can be identified individually. All of the various kinds of freight cars embody the common behavior described by the FreightCar class, but also have other characteristics that make them distinct from each other. Abstract classes are similar to interfaces in Java because they can specify methods without providing their implementation, and abstract classes cannot be instantiated. However, unlike interfaces, abstract classes are classes. They can have instance fields, and methods can be implemented. Classes that inherit from an abstract class must initialize the superclass just as if they extended a concrete class. Final Classes: Consider this situation: you have implemented security features in your Java application, but you know that anyone who can find out the names of the classes responsible for these features, they can extend them and override their methods, defeating your security. How can this be prevented? The answer is through final classes and/or methods. The final keyword, when used in a class declaration, prevents that class from being extended. When used in a method signature, the method cannot be overridden. The String class in the Java API is an example of a final class. This prevents someone from subclassing String to create a mutable String class that could be used wherever a String could be, and would then violate the expected behavior of String objects. An example of a final method might be a method to verify a password. Even if you allowed the class containing the method to be extended, you would not want the password verification method to be overridden. By declaring it final, this is prevented.