CS 3230 - Chap 6 Notes

Interfaces and Inner Classes

Not a lot in this chapter. Here's the high points.

Interfaces

What they are: (p.201) Conceptually, an interface is a way of indicating what a class should do and letting the class figure out how to do it.

What they have: (p.202) Just method stubs, no bodies.

Why Interfaces?

Short answer: an alternative approach to multiple-inheritance.

Longer answer: The pure-hierarchial model that characterizes most OO languages enforces a rigid scheme for inheritance. This is especially true of Java with the common ancestor Object and single-parent inheritance. There are occasions when it would be nice to inherit from more than one source, but multiple-parent inheritance carries with it a number of difficulties, not the least of which is figuring out whose method should be called when you have the "deadly diamond of death".

What's the Deadly Diamond of Death: Class A has a method called "foo". Two other classes, B and C derive from A and both override "foo". Class D inherits from both B and C and also overrides "foo". Make a list of references to each of these and call the method "foo" on each one, whose "foo" gets called?

Problems such as these led the Java designers to invent interfaces, a class-like thing that can be inherited by any class in the hierarcy.

Inheriting from Interfaces

How do I do it? (p.202 bottom) Use the implements keyword.

How many interfaces can I inherit? As many as you want. Contrast this to classes where you can only inherit from one parent. Example:

class MyFrame extends JFrame // inherits from JFrame
	// also inherits a bunch of stuff from the following listeners:
	implements ActionListener, KeyListener, FocusListener, WindowListener,
			MouseListener, MouseMotionListener
{
	...

Class relationships: The above MyFrame class and all the interfaces it implements share an "is-a" relationship. This means you could load a reference to an interface with any class that implements it.

How do I test if a class implements an interface? (p.205 top) use instanceof.

Differences Between Interfaces and Classes (p.205)

If you really want an interface to have instance variables that can be inherited or some methods with bodies, use an abstract class instead (p.206).

Applications of Interfaces

Comparisons: (p.202) Comparable interface has a compareTo() method that you can use for greater-than / less-than / equals tests.

Callbacks: (p.207) When we do GUI stuff, you guys will use interfaces all the time to handle events (the previous code snippet was a good example of what to expect).

Enumerations: Container classes can allow you to iterate through their contents by providing you with an Enumeration interface.

And plenty of others.

Making Your Own

It's just like declaring a class, only you use the word interface instead. (And be sure to observe all the above rules!)

Source Code: SimpsonFamily.java - Program that shows the use of interfaces.

Side note: Table Oriented Programming is an interesting article. A programmer describes an alternative to OO programming. In my most humble opinion, interfaces in Java can be used to accomplish many of the things he describes, but not all of them, and not in the same way.

Cloning (p.210)

It's not just for sheep anymore. You can clone objects in Java, too.

Review: Deep vs. Shallow Copy (p.211 bottom)

Shallow Copy: (p.210-211) When you assign one reference to another you create an alias as depicted on p.210, figure 6-1.

Deep Copy: (p.211 very bottom) Whey you assign all the contents of one object into another, you create a clone: an object that has the same state but a different identity (i.e. memory address)

The clone() method (p.211)

All classes inherit the clone() method from the universal superclass Object. You can override clone() in your classes to make a deep copy. (Sadly, clone() performs a shallow copy by default if you do not override it, which is a little counter-intuative.)

Clonable interface: (p.212) Interestingly, if you override clone() in your own class, you should also implement the Clonable interface (a tagged interface). You do not inherit clone() from this interface, you're just telling the compiler that your object supports cloning. (Don't feel bad if this sounds a little weird to you.)

Source Code: ShallowDeep.java - shows how shallow copies are made with plain assignments and how to make deep copies with the clone() method.

Inner Classes (p.215)

An inner class is a class declared within another class, just like you do it in C++. Example:

public class Outer {
	...
	private class Inner {
		...
	}
}

Why you would want to use one: (p.215) To make a class that can access all the members (public and private) of the containing (or "outer") class. The LinkedList source code on p.215 gives an example. You guys will use inner classes to handle GUI events when we get into the last half of the book.

Quandries with this pointer (p.219 bottom, p.220 top)

As mentioned, the this pointer can be used as a reference to the current instance of a class. But which class does this refer to in an inner class? Answer: the inner class. If you want a reference to the outer class you can qualify the this pointer with the name of the outer class.

public class Outer {
	private foo;
	...
	private class Inner {
		private foo;
		...
		void myMethod() {
			this.foo; // refers to Inner.foo
			Outer.this.foo; // refers to Outer.foo
		}
	}
}

Complexities of Inner Classes (p.220 middle)

Page 220 in your book raises some questions regarding inner classes. They do increase the complexity of the language and they have access to what should be "private" members of the outer class. Personally, I think the Java designers want you to use inner classes as an alternative to "friend" class idea in C++.

Class files generated by compiler for inner classes: (p.220 bottom) Note that the compiler puts little '$' dollar signs between the names of the outer and inner classes to generate a class file identifier.

Anonymous inner classes: (p.224 bottom)

These are kind of weird animals. Basically, they let you declare a class with no name. You'll do this a lot with GUI event handling. Here's an example:

JButton btn = new JButton("Push Me!");

// Next statement declares an anonymous inner class and passes the whole thing
// as a parameter to the addActionListener() method.  ActionAdapter is the
// parent class of the anonymous class.

btn.addActionListener(new ActionAdapter() {
	// here's a method
	public void actionPerformed(ActionEvent e) {
		// here's the method body
		System.out.println("Thanks for pushing me!");
	}
});

Static inner classes (p.227)

Basically, this is an inner class that has no reference to it's parent. The only reason you'd use it is to give the inner class a narrower scope than package scope. They are rarely used.

Proxies (p.230)

I'm not going to spend a lot of time on these. Suffice to say that a proxy class is one that you can create on the fly at run-time. This is easily done with interpreted languages (i.e. LISP, Perl, Python, etc.) but hard with compiled languages. Originally, they would compile the code and load the class file, all at run time (ouch). In addition to a performance hit, this was very inelegant, hence proxy classes were added to the language.

We will not be using proxies in this class, nor will I test you on them (except as maybe a single 1-point matching question) so I don't expect you to know all the ins and outs of them.