-
Enhancement
-
Resolution: Won't Fix
-
P4
-
None
-
8u60
-
x86
-
windows_8
A DESCRIPTION OF THE REQUEST :
This feature request is addressing the compilation error, "No enclosing instance of type X is accessible in scope".
As Java stands now, classes only have access to their own enclosing instances - "X.this" can only function if X is the class this class is nested in. I propose that classes also have access to the enclosing instances of their parent classes. As an example, class B is an inner class nested in class A, defined in a file A.java. Class C extends B, and is defined in a file C.java. C must make an intermediate constructor so that B generates with an enclosing instance of A, but C cannot reference the enclosing instance of A without storing it in an instance member. That is to say, C cannot reference the instance of A that encloses its parent B by using "A.this" as B can. The compilation error "No enclosing instance of type A is accessible in scope" occurs. Since there is no situation that would create confusion if C were to use "A.this" (as A.this can really only ever refer to one instance), I view this compilation error as a shortcoming rather than an actual error in design. In addition, perhaps the extending class should also be able to access the protected members of its parent's enclosing instance - inner classes can access the private members of their enclosing instance, so children of inner classes should be able to access the protected members.
JUSTIFICATION :
This is simply a design shortcoming in Java that would allow for greater functionality without causing any problems (at least, I can't see any problems). I actually was attempting to do this in an application of mine where I wanted to write a "ObjectRender" inner class that uses the members of its enclosing instance to render the virtual world object on the screen. Then I wanted a more specific version of the ObjectRender class to be created in a specific implementation package of the original API, but the descendant of ObjectRender could not even access its enclosing virtual object, let alone the same variables inside the virtual object that the general type of ObjectRender used. I understand some of the concern for access security - implementations of this feature could sidestep a "protected" modifier that prohibits external modification by using an instance of the inner class of the object, but that's a risk that can be handled by the original designers: implementers of this feature should understand that public inner classes can be overriden if not final, and can provide access to its enclosing instance's protected members, even if the enclosing type is final. They can protect themselves against these breaches by: making the enclosing type and inner type final, making the variables private instead of protected, making the inner type not public, or any combination of these.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
A class that extends an inner class should be able to access the enclosing instance of the inner class as if it is an enclosing instance of the new class (using "X.this", where X is the enclosing type of the parent type). The class should then be able to access the public members of the enclosing instance, and, optionally, the protected ones, as it is a descendant of the inner class. (Though that last one about protected is optional; honestly just being able to access the instance at all is the primary behavior that I'd like to see).
ACTUAL -
Currently, attempting to access the enclosing instance of a parent class using "X.this" where X is the enclosing type of the parent class results in a compilation error "No enclosing instance of type X is accessible in scope".
---------- BEGIN SOURCE ----------
The implementation would require two separate files:
A.java:
package myPackage;
public class A {
public void AGo() {
}
protected void AGoProtected() {
}
public class B {
public void BGo() {
A.this.AGo(); // B can access an enclosing instance A
}
}
}
C.java:
package myPackage;
import myPackage.A.B;
public class C extends B {
public C(A enclosingInstance) {
enclosingInstance.super(); // intermediate constructor handles establishing an
// enclosing instance
}
public void CGo() {
A.this.AGo(); // Feature request: This line throws a compilation error, but ideally it
// should call the public method of the parent enclosing type.
A.this.AGoProtected(); // Optional request: It might be good for the descendant to
// have access to the protected members of its parent's
// enclosing instance
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
This workaround is fully functional. The feature request is simply because a Java API implementation would be more "elegant" as it solves the compilation error in question rather than side stepping it, as the workaround does.
The easiest workaround will still allow for two separate files:
A.java:
package myPackage;
public class A {
public void AGo() {
}
public class B {
}
}
C.java:
package myPackage;
import myPackage.A.B;
public class C extends B {
private A enclosingInstance;
public C(A enclosingInstance) {
enclosingInstance.super();
this.enclosingInstance = enclosingInstance; // Keep the enclosing instance in an
// instance member of C
}
public void CGo() {
enclosingInstance.AGo(); // Reference the instance member of the workaround
}
}
This feature request is addressing the compilation error, "No enclosing instance of type X is accessible in scope".
As Java stands now, classes only have access to their own enclosing instances - "X.this" can only function if X is the class this class is nested in. I propose that classes also have access to the enclosing instances of their parent classes. As an example, class B is an inner class nested in class A, defined in a file A.java. Class C extends B, and is defined in a file C.java. C must make an intermediate constructor so that B generates with an enclosing instance of A, but C cannot reference the enclosing instance of A without storing it in an instance member. That is to say, C cannot reference the instance of A that encloses its parent B by using "A.this" as B can. The compilation error "No enclosing instance of type A is accessible in scope" occurs. Since there is no situation that would create confusion if C were to use "A.this" (as A.this can really only ever refer to one instance), I view this compilation error as a shortcoming rather than an actual error in design. In addition, perhaps the extending class should also be able to access the protected members of its parent's enclosing instance - inner classes can access the private members of their enclosing instance, so children of inner classes should be able to access the protected members.
JUSTIFICATION :
This is simply a design shortcoming in Java that would allow for greater functionality without causing any problems (at least, I can't see any problems). I actually was attempting to do this in an application of mine where I wanted to write a "ObjectRender" inner class that uses the members of its enclosing instance to render the virtual world object on the screen. Then I wanted a more specific version of the ObjectRender class to be created in a specific implementation package of the original API, but the descendant of ObjectRender could not even access its enclosing virtual object, let alone the same variables inside the virtual object that the general type of ObjectRender used. I understand some of the concern for access security - implementations of this feature could sidestep a "protected" modifier that prohibits external modification by using an instance of the inner class of the object, but that's a risk that can be handled by the original designers: implementers of this feature should understand that public inner classes can be overriden if not final, and can provide access to its enclosing instance's protected members, even if the enclosing type is final. They can protect themselves against these breaches by: making the enclosing type and inner type final, making the variables private instead of protected, making the inner type not public, or any combination of these.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
A class that extends an inner class should be able to access the enclosing instance of the inner class as if it is an enclosing instance of the new class (using "X.this", where X is the enclosing type of the parent type). The class should then be able to access the public members of the enclosing instance, and, optionally, the protected ones, as it is a descendant of the inner class. (Though that last one about protected is optional; honestly just being able to access the instance at all is the primary behavior that I'd like to see).
ACTUAL -
Currently, attempting to access the enclosing instance of a parent class using "X.this" where X is the enclosing type of the parent class results in a compilation error "No enclosing instance of type X is accessible in scope".
---------- BEGIN SOURCE ----------
The implementation would require two separate files:
A.java:
package myPackage;
public class A {
public void AGo() {
}
protected void AGoProtected() {
}
public class B {
public void BGo() {
A.this.AGo(); // B can access an enclosing instance A
}
}
}
C.java:
package myPackage;
import myPackage.A.B;
public class C extends B {
public C(A enclosingInstance) {
enclosingInstance.super(); // intermediate constructor handles establishing an
// enclosing instance
}
public void CGo() {
A.this.AGo(); // Feature request: This line throws a compilation error, but ideally it
// should call the public method of the parent enclosing type.
A.this.AGoProtected(); // Optional request: It might be good for the descendant to
// have access to the protected members of its parent's
// enclosing instance
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
This workaround is fully functional. The feature request is simply because a Java API implementation would be more "elegant" as it solves the compilation error in question rather than side stepping it, as the workaround does.
The easiest workaround will still allow for two separate files:
A.java:
package myPackage;
public class A {
public void AGo() {
}
public class B {
}
}
C.java:
package myPackage;
import myPackage.A.B;
public class C extends B {
private A enclosingInstance;
public C(A enclosingInstance) {
enclosingInstance.super();
this.enclosingInstance = enclosingInstance; // Keep the enclosing instance in an
// instance member of C
}
public void CGo() {
enclosingInstance.AGo(); // Reference the instance member of the workaround
}
}