The Artima Developer Community
Sponsored Link

Java Answers Forum
Private Inner Class Question

4 replies on 1 page. Most recent reply: Mar 5, 2004 9:08 PM by Kevin

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 4 replies on 1 page
Kevin

Posts: 25
Nickname: doublek321
Registered: Jan, 2004

Private Inner Class Question Posted: Mar 5, 2004 1:58 PM
Reply to this message Reply
Advertisement
This is probably easy for most of you but I'm still kind of a novice at Java. My question refers to the java code at the bottom of this message (taken mostly from an example in chapter 8 of Thinking In Java).

First off, it makes sense to me that the line below would compile because the left side of the expression is defined as "Contents" (which is a public interface).

Contents c = p.cont();



However, I don't understand how this line compiles...

System.out.println("c.value() = "+ c.value());


Why would the compiler let someone call a method from an interface unless there was a downcast?? Below is the way that I would have EXPECTED the call would HAVE to be made...

((Parcel3.PContents) c).value();


I realize that that WOULDN'T compile because Parcel3.PContents is a private class and, thus, there would be no access. But, that's why I don't understand why this thing works to begin with.

Can anyone explain it to me?



THE CODE IN IT'S ENTIRETY IS BELOW...

//: c08:TestParcel.java
// Returning a reference to an inner class.
// From 'Thinking in Java, 3rd ed.' (c) Bruce Eckel 2002
// www.BruceEckel.com. See copyright notice in CopyRight.txt.
 
/* 
This exists in file "Contents.java" and is, thus, accessible here

public interface Contents {
  	int value();
}
*/
 
class Parcel3 {
	private class PContents implements Contents {
		private int i = 11;
		public int value() { return i; }
	}
		
	public Contents cont() {
		return new PContents();
	}
}
	
public class TestParcel {
	public static void main(String[] args) {
		Parcel3 p = new Parcel3();
		Contents c = p.cont();
		
		if (c instanceof Contents) {
			System.out.println("it's Contents");
		}
		
		System.out.println("c.value() = "+ c.value());
	}
} ///:~


twc

Posts: 129
Nickname: twc
Registered: Feb, 2004

Re: Private Inner Class Question Posted: Mar 5, 2004 4:38 PM
Reply to this message Reply
> First off, it makes sense to me that the line below would
> compile because the left side of the expression is defined
> as "Contents" (which is a public interface).
>
>
> Contents c = p.cont();
> 

c is actually an PContents object since the method returns a PContents object. Since the PContents class implements the Contents interface, c can also be considered to be a Contents object. At this point in the code, the compiler only realizes that c is a Contents object.

An analogy might be if Sue Smith marries John Jones, she is considered both a Smith and a Jones. (Why we rarely think of men as being both is another issue.) If you see her at a Smith family reunion, you would know she is a Smith (but might not know whether that is by blood or marriage). Ditto if she's at the Jones reunion.

Any class that implements a particular interface can be considered an object of that type. For example, the Integer, Double, and String class all implement the Comparable interface. Therefore they can all be considered Comparable objects as well as objects of their own type.

> However, I don't understand how this line compiles...
>
>
> System.out.println("c.value() = "+ c.value());
> 

>
> Why would the compiler let someone call a method from an
> interface unless there was a downcast?? Below is the way
> that I would have EXPECTED the call would HAVE to be
> made...

What an interface does is guarantee that certain methods exist. For example, all Comparable objects are required to have an int method named compareTo(Object o) and a boolean method named equals(Object o). These methods must work in a fashion specified by the interface.

The Contents interface probably requires that the value() method return an int value. If that is the case, then the compiler knows that all Contents objects have a value() method and have no reason not to compile this code.

On the other hand, suppose that the PContents class had another method called foo() that was NOT required by the Contents interface. Then c.foo() would cause a compiler error since the compiler (at this point in the code) only knows that c is a Contents object (which wouldn't be guaranteed to have a foo() method).

>
> ((Parcel3.PContents) c).value();
> 

>
> I realize that that WOULDN'T compile because
> Parcel3.PContents is a private class and, thus, there
> would be no access. But, that's why I don't understand
> why this thing works to begin with.

Ignoring the private class issue, the beauty of Interfaces is that you DON'T have typecast! While you can't compare Integers to Strings, even though both are Comparable objects, you know that both have certain characteristics.

That makes a method such as what I have below possible.
public Comparable[] sort(Comparable[] array)
{
    //code to sort the array
}


Such a method could sort an array of Strings, then sort an array of Integers, because both use the Comparable interface which guarantees that the objects will have a compareTo method that determines if the given objects value is less than, greater than, or equal to the parameter objects value.

You cannot sort a mixed array (since you can't compare Strings to Integers), but it allows the method to be reusable.

I hope this helps.

twc

Kevin

Posts: 25
Nickname: doublek321
Registered: Jan, 2004

Re: Private Inner Class Question Posted: Mar 5, 2004 7:45 PM
Reply to this message Reply
First off, thanks you very much for putting in so much time to write such an in-depth answer. I really do appreciate that! Unfortunately, I guess I have a follow-up question (related to the code at the bottom of this post)...

In this example the following line in main (if uncommented) would give a compiler error...

A.DImp2 di2 = a.getD();


To me it seems like the example in this file is very similar to the other example in the other file (with the exception being that this one doesn't compile). Here's why...

-In the other example, we were able to use a nested public method (cont) to give us access to a method (value) in a nested private class (PContents).

-In this example, we use a nested public method (getD) to try to give us access to a nested private interface (D) even though it's really a "DImp2" casted into a "D". My question is why does the compiler complain in this example but not in the other one?

HERE'S THE CODE IN ITS ENTIRETY FOR THIS EXAMPLE...
class A {
	private interface D {
		void f();
	}
	
	public class DImp2 implements D {
		public void f() {}
	}
	
	public D getD() { return new DImp2(); }
 
	
	public static void main(String[] args) {
		A a = new A();
		// Doesn't return anything but A.D:
		//A.DImp2 di2 = a.getD();
	}
}

twc

Posts: 129
Nickname: twc
Registered: Feb, 2004

Re: Private Inner Class Question Posted: Mar 5, 2004 7:59 PM
Reply to this message Reply
> First off, thanks you very much for putting in so much
> time to write such an in-depth answer. I really do
> appreciate that! Unfortunately, I guess I have a
> follow-up question (related to the code at the bottom of
> this post)...

No problem. It helps me understand things better when I have to think about them.

> In this example the following line in main (if
> uncommented) would give a compiler error...
>
>
> A.DImp2 di2 = a.getD();
> 

All I can venture is an educated guess. I don't think A.DImp2 is considered the name of a class. I suspect that if you change the line to the following, that it will compile (I'm not at a machine with the SDK on it, so I can't test it myself).

DImp2 di2 = a.getD();


If that doesn't compile, then I'm not sure what the problem is.

BTW, I've never seen code like this with a public class inside a non-public one. Since it compiled, it must be OK. Is this something that you got out of "Thinking In Java"?

twc

Kevin

Posts: 25
Nickname: doublek321
Registered: Jan, 2004

Re: Private Inner Class Question Posted: Mar 5, 2004 9:08 PM
Reply to this message Reply
> > In this example the following line in main (if
> > uncommented) would give a compiler error...
> >
> >
> > A.DImp2 di2 = a.getD();
> > 

> All I can venture is an educated guess. I don't think
> A.DImp2 is considered the name of a class. I suspect that
> if you change the line to the following, that it will
> compile (I'm not at a machine with the SDK on it, so I
> can't test it myself).

It didn't compile. Got the following error message...


NestingInterfaces2.java:17: incompatible types
found : A.D
required: A.DImp2
DImp2 di2 = a.getD();



> BTW, I've never seen code like this with a public
> class inside a non-public one. Since it compiled, it must
> be OK. Is this something that you got out of "Thinking In
> Java"?

I got it out of chapter 8 of "Thinking In Java" but I cut out pieces of the code that were extraneous to my question.

I ordered the seminar CD yesterday hoping that that would help clear up my questions (when it arrives hopefully it will and I'll post the reasoning). I guess this topic is fairly complicated.

Flat View: This topic has 4 replies on 1 page
Topic: Java IO : Opened Files Previous Topic   Next Topic Topic: ejecting CD Drive

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use