|
Re: Protected Inner Classes
|
Posted: Aug 9, 2004 5:20 PM
|
|
Two things need to be explained to understand the compiler error you are getting.
1. The access modifier supplied by Java compiler for default constructor.
2. Meaning of protected inner class and protected constructor
You may already know both of these. However, I will explain these two things in context of your compiler error.
1. When you define a class then you can have its access modifier as package-level or public for top-level class or private, protected, public or package level for inner class. If you don't specify any constructor for a class (top ort inner) then Java compiler adds a default constructor and the access modifier for the added default constructor is same as the class's access modifier. Therefore, when you defined you class C2 as:
package pkg2:
import pgk1.*;
public class C2
{
protected int i2 = 2;
protected class C2Inner1 implements I1
{
public void method1()
{ System.out.println("This is C2Inner1.method1."); }
}
}
then it is same as writing:
package pkg2:
import pgk1.*;
public class C2
{
protected int i2 = 2;
public C2() {
}
protected class C2Inner1 implements I1
{
protected C2Inner() {
// Note the protected modifier for this constructor
}
public void method1()
{ System.out.println("This is C2Inner1.method1."); }
}
}
2. The second point to note here is the access to a protected member of a class. A protected member can be accessed inside its descendent or in the same package. Since C2Inner class has protected access, you can use its name i.e. C2Inner anywhere in pkg2 or inside any class which inherits C2. Note that C2Inner class being declared protected gives you access to its name in C3 because C3 extends C2. By the phrase "access to its name", I mean you can declare a reference variable of type C2Inner anywhere inside C3 as;
C2Inner myc2Inner;
So, the above declaration in C3 is fine because C2Inner is inherited by C3 by virtue of its being protected member of C3's ancestor. However, when you try to create an object of C2Inner class then you are trying to use the constructor of C2Inner class. Whether you can use the constructor or not depends on the constructor's access modifier. Since you didn't supply any constructor for C2Inner, its default constructor will have protected modified as shown in above example. Now to write
new C2Inner();
you must have access to C2Inner(), which is C2Inner's constructor. Apply the same logic for accessing the protected member. Since C2Inner() constructor is protected, you can access it only in the same package as pkg2 or in a class, which inherits C2Inner class. Since C2 class satisfies neither of the conditions, you cannot write
new C2Inner();
inside C3.
The only way to use the above statement in C3 is to make the C2Inner() constructor public. You may argue that there were some reasons to keep C2Inner protected and so you want to make its constructor public. I don't know your exact requirement. So, I don't want to give you any advice on this one.
However, try this changed definition of C2 and then C3 will compile.
package pkg2;
import pkg1.*;
public class C2
{
protected int i2 = 2;
protected class C2Inner1 implements I1
{
public C2Inner1() {
}
public void method1() {
System.out.println("This is C2Inner1.method1."); }
}
}
To experiment with protected constructor of C2Inner you can also try another way. Don't make any changes in C2 class. That is, leave the default constructor supplied by Java compiler protected. Inside C3, declare an inner class that inherits C2Inner and return an object of that class from C3. This is shown below.
package pkg3;
import pkg1.*;
import pkg2.*;
class C3 extends C2
{
class C22 extends C2Inner1{
}
I1 createC2Inner1()
{
C3 z = new C3();
return new C22();
//return z.new C2Inner1(); // Line 1
// return new C2Inner1(); // Line 2
// return new C3.C2Inner1(); // Line 3
// return new z.C2Inner1(); // Line 4
}
public static void main(String[] args)
{
C3 a = new C3();
a.i2 = 3; // Line 5
I1 x = a.createC2Inner1();
x.method1();
}
}
This time C22 was able to access the protected constructor of C2Inner because it inherits C2Inner.
Thanks Kishori
|
|