Why creating an object of the subclass also invokes the constructor of the superclass?
Show
Subclassing and InheritanceClasses in Java exist in a hierarchy. A class in Java can be declared as a subclass of another class using the
In this example, an object of type A class can extend only one other class. To use the proper terminology, Java allows single inheritance of class implementation. Later in this chapter, we’ll talk about interfaces, which take the place of multiple inheritance as it’s primarily used in other languages. A subclass can be further subclassed. Normally, subclassing specializes or refines a class by adding variables and methods (you cannot remove or hide variables or methods by subclassing). For example:
The A subclass inherits all members of its superclass not designated as
Figure 6-1. A class hierarchy The Shadowed VariablesIn Chapter 5, we saw that a local variable of the same name as an instance variable shadows (hides) the instance variable. Similarly, an instance variable in a subclass can shadow an instance variable of the same name in its parent class, as shown in Figure 6-2. We’re going to cover the details of this variable hiding now for completeness and in preparation for more advanced topics, but in practice you should almost never do this. It is much better in practice to structure your code to clearly differentiate variables using different names or naming conventions. In Figure 6-2, the variable Figure 6-2. The scope of shadowed variables In the previous example, all variables were of the same type. A slightly more plausible use of shadowed
variables would involve changing their types. We could, for example, shadow an Here’s a simple example:
In this example, we shadow the instance variable Because both variables exist in
Inside of
Another important point about shadowed variables has to do with how they work when we refer to an object by way of a less derived type (a parent type). For example, we can refer to a
The same would be true if we accessed the object using an explicit cast to the To reiterate, the usefulness of shadowed variables is limited. It’s much better to abstract the use of variables like this in other ways than to use tricky scoping rules. However, it’s important to understand the concepts here before we talk about doing the same thing with methods. We’ll see a different and more dynamic type of behavior when methods shadow other methods, or to use the correct terminology, override other methods. Overriding MethodsIn Chapter 5, we saw that we could declare overloaded methods (i.e., methods with the same name but a different number or type of arguments) within a class. Overloaded method selection works in the way we described on all methods available to a class, including inherited ones. This means that a subclass can define additional overloaded methods that add to the overloaded methods provided by a superclass. A subclass can do more than that; it can define a method that has exactly the same method signature (name and argument types) as a method in its superclass. In that case, the method in the subclass overrides the method in the superclass and effectively replaces its implementation, as shown in Figure 6-3. Overriding methods to change the behavior of objects is called subtype polymorphism. It’s the usage most people think of when they talk about the power of object-oriented languages. Figure 6-3. Method overriding In Figure 6-3, From what you’ve seen so far, overridden methods probably look like they shadow methods in superclasses, just as variables do. But overridden methods are actually more powerful than that. When there are multiple implementations of a method in the inheritance hierarchy of an object, the one in the “most derived” class (the furthest down the hierarchy) always overrides the others, even if we refer to the object through a reference of one of the superclass types.[17] For example, if we have a
In other words, for purposes of behavior (invoking methods),
a @Override
A common programming error in Java is to accidentally overload a method when trying to override it. Any difference in the number or type of arguments (the method signature) produces two overloaded methods instead of a single, overridden method. The new annotations syntax in Java 5.0 provides a way to get the compiler to help with this problem. An annotation, as we’ll describe in
Chapter 7, allows us to add special markers or metadata to source code that can be read by the compiler or runtime tools. One of the standard annotations that Java defines is called
Overridden methods and dynamic bindingIn a previous section, we mentioned that overloaded methods are selected by the compiler at compile time. Overridden methods, on the other hand, are selected dynamically at runtime. Even if we create an instance of a subclass our code has never seen before (perhaps a new class loaded over the network), any overriding methods that it contains are located and used at runtime, replacing those that existed when we last compiled our code. In contrast, if we created a new class that implements an additional, more specific, overloaded method, and replace the compiled class in our classpath with it, our code would continue to use the implementation it discovered originally. This situation would persist until we recompiled our code along with the new class. Another effect of this is that casting (i.e., explicitly telling the compiler to treat an object as one of its assignable types) affects the selection of overloaded methods at compile time but not overridden methods. In practice what we’ve just described is not something you need to worry about often, but it’s important in understanding what the virtual machine does and does not do at runtime. Static method bindingStatic methods don’t belong to any object instance; they are accessed directly through a class name, so they are not dynamically selected at runtime like instance methods. That is why static methods are called “static”; they are always bound at compile time. A static method in a superclass can be shadowed by another static method in a subclass, as long as the original method was not declared final. However, both methods are always accessible directly via their respective class names. You can’t “override” a static method with an instance method. In other words, you can’t have a static method and instance method with the same signature in the same class hierarchy. final methods and performance In languages like C++, the default is for methods to act like shadowed variables, so you have to
declare explicitly the methods you want to be dynamic (or, as C++ terms them, virtual). In Java, instance methods are, by default, dynamic. But you can use the We have seen In the old days, dynamic method binding came with a significant performance penalty, and some people are still inclined to use the Compiler optimizationsIn some older versions of Java, the javac compiler can be run with a -O switch, which tells it to perform certain optimizations, like inlining, statically. Most of these optimizations are now done at runtime by smarter VMs, so switches like this are generally not necessary. Another kind of optimization allows you to include debugging code in your Java source without incurring a size or performance penalty. Although
Java doesn’t have a preprocessor to explicitly control what source is included, you can get some of the same effects by making a block of code conditional on a constant (i.e.,
In this case, the compiler can recognize that the condition on the Note that this kind of debugging code is useful for purposes such as logging. In contrast to assertions, which we covered in Chapter 4, which are supposed to be yes/no tests that guarantee the correctness of your program logic, these conditional blocks of code might do expensive formatting or other output processing that is useful during develoment but you don’t wish to have around in the final product. Method selection revisitedBy now you should have a good, intuitive feel for how methods are selected from the pool of potentially overloaded and overridden method names of a class. If, however, you are dying for more detail, we’ll provide it now. In a previous section, we offered an inductive rule for overloaded method resolution. It said that a method is considered more specific than another if its arguments are assignable to the arguments of the second method. We can now expand this rule to include the resolution of overridden methods by adding the following condition: to be more specific than another method, the type of the class containing the method must also be assignable to the type of the class holding the second method. What does that mean? Well, the only classes whose types are assignable are classes in the same inheritance hierarchy, meaning that we’re talking about the set of all methods of the same name in a class or any of its parent or child classes. Because subclass types are assignable to superclass types, but not vice versa, the resolution is pushed in the way that we expect down the chain toward the subclasses. This effectively adds a second dimension to the search, in which resolution is pushed down the inheritance tree toward more refined classes and, simultaneously, toward the most specific overloaded method within a given class. Exceptions and overridden methods An overriding method may change the behavior of an object, but in some ways, it must still fulfill the contract of the original method with the user. Specifically, an overriding method must adhere to the So the new method may declare exactly the same checked exceptions as the original, or it has the option to refine those types by declaring that it throws more specific subtypes than the overridden method. This is not the same as just saying that the method can simply throw subtypes of its declared exceptions; any method can do that. The new method can actually redefine the Let’s quickly review what the
When we call this method, the compiler will ensure that we allow for the possibility of any kind of When we override a method in a subclass, we get an opportunity to rewrite the
In this code,
On the other hand, if we don’t care why the food is inedible, we’re free to guard for the more general To sum up, an overriding method can refine not only the behavior of the parent method, but also the type of checked exceptions it throws. Next, we’ll talk about overridden methods that change their return type in exactly the same way. Return types and overridden methods For a method to qualify as an overridden method in a subclass, it must have exactly the same number and types of arguments. It must have the same “inputs,” as it were. As we saw in the previous section, overriding methods may refine their “output” to some extent. Namely, they can narrow their What this means is that when you override a method, you may change the return type to a subtype of the original method’s return type. For example, if our
As we’ll see later, this coding technique is very helpful because it eliminates some runtime casting of objects. Special References: this and super The special references
In this example, our
Casting A cast explicitly tells the compiler to change the apparent type of an object reference. The main use for casts is when an object is temporarily assigned to a more general type. For example, if a Attempting to cast an object to an incompatible type at runtime results in a A cast can be used to narrow or downcast the type of a reference—to make it more specific. Often, we’ll do this when we have to retrieve an
object from a more general type of collection or when it has been previously used as a less derived type. (The prototypical example is using an object in a collection, as we’ll see in Chapter 11.) Continuing with our
We can’t reassign the reference in What all this means is that you can’t lie or guess about what an object is. If you have a
As we
mentioned earlier, casting can affect the selection of compile-time items such as variables and overloaded methods, but not the selection of overridden methods. Figure 6-4 shows the difference. As shown in the top half of the diagram, casting the reference Figure 6-4. Casting and selection of methods and variables Casting aspersionsCasting in Java is something that programmers strive to avoid. This is not only because it indicates a weakness in the static typing of the code, but because casts can also simply be tedious to use and make code less readable. Unfortunately, a great deal of code written in Java in the past has had no choice but to rely on casting so that it can work with any type of object the user requires. Java 5.0 introduced a major new language feature, generics, partly to address this issue. Generics allow Java code to be “typed” for a particular kind of object by the user, eliminating the need to cast in many situations. We’ll cover generics in detail in Chapter 8 and see how they reduce the need for casts in most Java code. Using Superclass Constructors When we talked earlier about constructors, we discussed how the special statement
If we are going to call a superclass constructor with
In this example, we use Instance variables of the class are initialized upon return from the superclass constructor, whether that’s due
to an explicit call to Full Disclosure: Constructors and InitializationWe can now tell the full story of how constructors are chained together and when instance variable initialization occurs. The rule has three parts and is applied repeatedly for each successive constructor that is invoked:
Abstract Methods and Classes A method in Java can be declared with the
In Java, a class that contains one or more abstract methods must be explicitly declared as an abstract class, also using the
An abstract class can contain other nonabstract methods and ordinary variable declarations, but it can’t be instantiated. To be used, it must be subclassed and its abstract methods must be “overridden” with methods that implement a body. Not all abstract methods have to be implemented in a single subclass, but a subclass that doesn’t
override all its superclass’s abstract methods with actual, concrete implementations must also be declared
Abstract classes provide a framework for classes that is to be “filled in” by the implementer. The When you create an object of a subclass the constructor of the superclass calls the constructor of the subclass True or false?(*2) A subclass constructor always calls the constructor of its superclass, and so on up to the Object constructor, to initialize all the aspects of the instance that the subclass inherits from its superclass.
How does a subclass invoke its superclass constructor?To explicitly call the superclass constructor from the subclass constructor, we use super() . It's a special form of the super keyword. super() can be used only inside the subclass constructor and must be the first statement.
When you instantiate a subclass the superclass constructor will be also invoked?Answer: Yes, this is absolutely true. Because of course without the superclass constructor invoked the global variables of tge super class and its function won't be able to work.
Can superclass constructors be invoked from subclasses?A subclass can call a constructor defined by its superclass by use of the following form of super: super(parameter-list); Here, parameter-list specifies any parameters needed by the constructor in the superclass.
|