Getting Your Inheritance

     

I bet that "getting your inheritance" pun has been made a thousand times. I think I will leave it in anyway and try to pass it off to you like, "Yeah, we both know that that dumb joke has been made so many times. But it's not simply some somnambulist tech writer digging into the dregs of his already shallow literary toolbox and pulling out yet another overused bad pun. Rather, in my deft hands, it's another brilliant and hilarious example of a master of 'high camp' confidently practicing his craft."

I'm not sure I like where this is going. Let me start all over. Okay.

Java classes all participate in inheritance, whether they like it or not, and whether they know it or not.

No! Somehow that comes off as angry ”too angry . I'm not angry about inheritance. Geez. Try again:

Inheritance in Java, as in life, is when you get something for nothing. [This is [Following is a Continuation Paragraph...] too preachy, too absent, and drippy. Note to self: Don't liken things to "life" as if "life" is somewhere else and you know something about it. This can be annoying, despite the incredible insight. Just tone it down a bit, okay? Is that so hard? Gawd.]

Every Java class has an implicit superclass: java.lang.Object. That is to say, the class called Object in the java.lang package (which you recall is automatically imported for you into every class) is the parent of every other class in Java that has ever been, or will ever be, made. Any person we make (that is, any object of the class Person we instantiate) is an object.

It makes sense that Person needs to know something other than just how to be a Person ”it needs to know how to live inside Javaland. Every object of every class needs to know that information. It needs to be able to be constructed in the first place, and it needs to be able to participate in threads and such. That behavior is necessarily shared by every Java class. So for that reason, java.lang.Object is the superclass of every other Java class, which we can call the subclasses of java.lang.Object .

There are a few terms that we can use to mean the same thing:

Superclass = A class that is higher up in the hierarchical inheritance tree.

Parent class = Superclass.

Subclass = A class lower in the hierarchical inheritance tree than another class.

Child class = Subclass

So Person is a subclass of Object. Person is a child class of Object. Object is the superclass of Person. Object is the parent class of Person. We'll use these terms interchangeably to try to keep you awake.

If you want to, you can declare that your class will inherit the data ( members ) and functionality ( methods ) from one other class. You do so using the extends keyword.

But wait! When we declared the Person class, we did it like this:

 

 public Person { ... } 

Where's the part about Object? Where's this "extends" you speak of? They are implicit. The following code is equivalent to the preceding code:

 

 public Person extends java.lang.Object { ... } 

Classes can have only one immediate parent class. The following is not legal :

 

 public Person extends LivingCreature, Homosapiens { ... } //illegal! busted! 

Multiple inheritance is a thing allowed in C++, and the Java language designers thought that it made code very confusing and difficult to debug and maintain. So they decided not to allow it at all. Internet people hanging around in forums complain on occasion that disallowing multiple inheritance makes it hard to do certain things in the language, and that it was a bad decision. I say, "Ah, hog wash." Java allows interfaces, which you can read about in the exciting chapter 17, intriguingly named, "Interfaces." You can implement multiple interfaces, and that kind of solves that problem, which I don't necessarily recognize as a problem, because in my experience, if you've got a good design, you won't feel any need to inherit from more than one class. In fact, I'll play this card: If you find yourself at your desk thinking, "Man, I can't do what I need to this way. I wish I could extend more than one class ," you should rethink your design. Really. The issue of only allowing single inheritance is a non-issue.

graphics/fridge_icon.jpg

FRIDGE

Remember that children cannot see their parent's private members. In psychiatric circles such an episode is referred to as "The Freudian Scene," and can have long- lasting effects on the child. :)


To help you think about this kind of thing, make sure to look at the "IS-A Thing" and "HAS-A Thing" sections later in this chapter. Meanwhile, back at the ranch Because every class extends Object, they each get to call all of the public methods that Object implements, as if they were Object itself.

Object has the following public methods:

 

 toString(), equals(), hashCode(), getClass(), notify(), notifyAll(), wait(). 

That means that you can call those methods on every Person object, even though they aren't defined in the Person class. You get that functionality for free.

Here are some things to remember about inheritance. If a member has protected visibility, any subclass of that member's class can access it because protected = package + children. A subclass can only see the protected members through inheritance. Private members are not visible to subclasses.

Methods Can Override Superclass Methods

Sometimes, what you get from a parent isn't exactly what you wanted or needed. Perhaps you can relate to that. :(. In that case, you might want to make a new implementation of the method you inherited from them. In Java, this is called overriding. In the real world I believe it's called therapy .

You can implement a method that is defined in a superclass however you want to. Nevertheless, the method signatures must match when you do this. If the signatures don't match, you aren't overriding anything; you're simply making a new method that has the same name , but different signature. If the signatures don't match, the compiler will be able to sort out which method you mean to call when. But if a subclass overrides a method that is implemented in a superclass, the runtime will call the subclass method on all instances of the subclass type. It just slides it right in there and replaces it. It makes the superclass method invisible to the subclass. Here's an easy example to demonstrate .

Let's take our Person class that we already have and extend it to make a Programmer class. We'll then extend Programmer with JavaProgrammer. The code, as always, is heavily commented so you can see what's happening line by line.

Programmer.java
 

 package net.javagarage.demo.inherit; /*  * We'll just do some dumb printlns.  * Notice that Person is in another package,  * so we either need to import it or simply write  * out the fully qualified name like this in the  * extends statement.  */ public class Programmer extends                   net.javagarage.demo.classes.Person {       String onlineName;       void writeCode(String someCode){             System.out.println("The code: " +                  someCode);       }       void slackOff(long duration){             System.out.println(                  "Now slacking in the hallways " +             "for the next " + duration +                  " minutes.");       }       void screwAroundOnInternet(String site){             System.out.println("Now screwing around                  at " + site);       }       void portProgram(String fromPlatform, String                  toPlatform){             System.out.println(                  "Spending the rest of the year " +             "moving the app from " + fromPlatform +                   " to " + toPlatform);       } } 

JavaProgrammer.java
 

 package net.javagarage.demo.inherit; /*  Define a subclass of programmer that is a specific type of programmer that can do all the same things as Programmer, and other, more specific things.  */ public class JavaProgrammer extends Programmer {       //this method is the override of portProgram       //defined in the superclass Programmer       void portProgram(String from, String to){            System.out.println("No port necessary: " +             "the same Java code runs on both " +            from + " and " + to);       }       //now define some new method that       //only Java programmers do       void goToJavaOneConference(){            System.out.println("Going to JavaOne...");       } } 

OverrideDemo.java
 

 package net.javagarage.demo.inherit; /**  * All this does is make an object of type  * JavaProgrammer and demos how the methods it  * inherits (and the one it overrides) work  */ public class OverrideDemo{       public static void main(String[] args) {             //create new instance of JavaProgrammer             //the JavaProgrammer jp = new                      JavaProgrammer();           //inherited member from Person           jp.name = "Jane";           //inherited from Programmer           jp.onlineName = "Veruca Salt";           //defined in Programmer           jp.writeCode("<blink>Buy now!</blink>");           //inherited method from Programmer           jp.screwAroundOnInternet("javagarage.net");           //overridden method defined in both           //Programmer and JavaProgrammer           //but this object's reference type is           //JavaProgrammer, so guess which method           //gets called...jp.portProgram           //("Windows", "Linux");           //also from Programmer           jp.slackOff(147);           //just a regular method defined only           //in JavaProgrammer.           //well, my work here is done...           jp.goToJavaOneConference();      } } 

Here is the output of running the class.

 

 The code: <blink>Buy now!</blink> Now screwing around at javagarage.net No port necessary: the same Java code runs on both Windows and Linux Now slacking in the hallways for the next 147 minutes. Going to JavaOne... 

This code clearly shows how things work when one class extends another and overrides its methods. I hope it clearly shows that anyway, because I think that's enough talking about it.

IS-A Thing

This is more of a design issue, not something that is proper to the Java programming language. But design is important. I think that elsewhere in this book I am going to suggest that the design is the implementation. Think about that for a moment. It washes over you like a mantra: the design is the implementation .

Java code is written as a collection of classes. Some programs are 1 class, many are between 100 and 1000 classes, and some are more than that. When you start dealing with a lot of classes, you need to think carefully about how to divide up your classes. One way to do that is the subject of this topic: inheritance. If class B inherits from class A, we say that B "is an" A. Say you have a class called Vehicle, which is the superclass of Car. Car inherits from Vehicle. Car extends Vehicle (those mean the same thing). A Car is a Vehicle. Car is a specific kind of Vehicle. A Cat IS A Feline. A Feline IS A Animal ( excuse my grammar). You know that Animal is a superclass that Feline extends, and Cat extends Feline.

Thinking about IS-A relationships will help you get your inheritance issues straightened out, help you communicate with your analysts and other programmers, and help you make a well-designed program. Don't change the channel before reading HAS-A Thing. They kind of go together.

HAS-A Thing

The other kind of relationships in Java dare I say programming is the HAS-A relationship. HAS-A means the properties of this class. A Car HAS-A engine. A Car HAS-A collection of tires. A Car has a maximumNumberOfPassengers. A Car HAS-A type, such as sedan, compact, sporty, or whatever. You get the idea.

When designing your applications, say to yourself, "What is this thing? What properties does it have?" After you know the answers to the IS-A and HAS-A questions, you should first make sure that some of the properties don't actually belong to a superclass, and then you have your basic class skeleton. Like this:

 

 public class Car extends Vehicle {      private Engine engine;      private Tire[] tires;      private short maxNumberOfPassengers;      private String carType;      //... getter and setter methods } 

Now all you need to do is figure out what a Car does in the context of your application, and you're off.

Classes Can Ensure That No Class Inherits from Them

graphics/fridge_icon.jpg

FRIDGE

The only modifiers allowed in a class declaration are public , final , and abstract . A class cannot be both final and abstract .

The final keyword can be applied to classes, methods, and variables , and means roughly the same thing for each.


Sometimes, you want to make sure that no class ever will be able to inherit functionality from your class. Because of polymorphism, which you can read about in Chapter 16, "Abstract Classes," and others, situations may arise when you want to ensure that the improper substitution of one class for another does not break your application or cause a security problem.

In these cases, you can declare a class to be final . You do so in the class declaration, like this:

 

 public final class String {...} 

That's right. The class java.lang.String is a final class. The designers of the Java language were prescient enough to see that allowing Strings to be subclassed would lead to security risks. We'll examine this in greater depth in Chapter 13, "Strings," but for now, it is enough to understand the following possible scenario: you run an application that gains access to the local file system by substituting a subclass of String with a rewritten value (containing a path ) that the user might not knowingly provide. Because Strings are immutable (cannot be modified), and because they are final, this sort of thing does not happen in Javaland.

Unless you are writing fairly low-level code that you anticipate causing a possible security breach, you may not find many occasions to declare your classes final .

In the following chapter we switch gears a bit, and discover how to use Strings in some depth. Strings are among the most common programming elements you will use, and there are deceptively subtle aspects to their behavior. So we switch out of talking about classes in general and how they behave, and move into talking about a specific and very popular class that comes with the Java API: that lovable sequence of characters known as java.lang.String.



Java Garage
Java Garage
ISBN: 0321246233
EAN: 2147483647
Year: 2006
Pages: 228
Authors: Eben Hewitt

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net