Is it possible for the nested inner classes ABar and BBar to access main class's variables? For example:
public class Foo {
public ABar abar = new ABar();
public BBar bbar = new BBar();
public int someCounter = 0;
public class ABar {
public int i = 0;
public void someMethod(){
i++;
someCounter++;
}
}
public class BBar {
public void anotherMethod(){
bbar.someMethod();
someCounter++;
}
}
}
// then called using: //
Foo myFoo = new Foo();
myFoo.bbar.anotherMethod();
Edit
Seems the code I typed would have worked if i'd have tried it first; was trying to get help without being too specific. The code I'm actually having trouble with
Fails because of the error 'cannot make static reference to the non-static field stage'
public class Engine {
public Stage stage = new Stage();
// ...
public class Renderer implements GLSurfaceView.Renderer {
// ...
#Override
public void onDrawFrame(GL10 gl) {
stage.alpha++;
}
}
public class Stage extends MovieClip {
public float alpha = 0f;
}
In your code, yes, it is possible.
Non-static nested classes (inner classes) have access to other members
of the enclosing class, even if they are declared private. Static
nested classes do not have access to other members of the enclosing
class.
See: Nested Classes
If your inner class extends the outer class, then it will have access to the outer class public and protected members. I just tired it and it worked. The construct is a bit odd, because it implies a sort of infinite loop in the class definition, but it seems to do the job.
Related
I switched from C++ to Java and have a problem with nested classes. I would like to initiate an instance of a subclass in the constructor of the superclass. I tried it like this, but it seems to be wrong.
public class Aircraft {
public class LandingGear {
}
public Aircraft() {
Aircraft.LandingGear myLandingGear = this.new LandingGear();
}
}
The idea is that every instance of the class Aircraft has an instance "myLandingGear" of the subclass LandingGear.
For this use case, your nested class should be static (if it's going to be nested at all), and then you just use a simple new:
public class Aircraft {
public static class LandingGear {
// ----^
}
public Aircraft() {
Aircraft.LandingGear myLandingGear = new LandingGear();
// --------------------------------------^^^^
}
}
When it's not static, it's an inner class, which from your description isn't what you want. More on nested classes in this Java tutorial.
But unless there's a really good reason for LandingGear to be nested inside Aircraft, consider making it a peer instead.
Every Aircraft will have a LandingGear
public class Aircraft {
private LandingGear myLandingGear;
public Aircraft() {
myLandingGear = new LandingGear();
}
public LandingGear getLandingGear() {
return this.myLandingGear;
}
}
public class Aircraft {
public class LandingGear {
public static void m1()
{
//Your code snipet
}
}
public Aircraft() {
LandingGear.m1();
}
}
when you extend a private class. Are the public and protected members of class become private. if not any explanation.
if you extend a nested private class, it wont change public/protected modifiers of the members. Here is an example :
public class Clazz {
private static class NestedClazz {
public int value = 123;
}
public static class NestedClazzExt extends NestedClazz {
}
}
you can now access the inherited member: value from outside
public static void main(String[] args) {
NestedClazzExt nestedClazz = new Clazz.NestedClazzExt();
System.out.println(nestedClazz.value);
}
you can create private class in side a class . We call it as Nested classe. Means a class inside a class. The Concept itself is saying that you can create private class in side another class. The private class will act like as data member to the outer class.
So, You can't extend the private class.
Based on your query I tried to prepare a simple class.
public class pvtClass {
private class As {
public String abc = "private attribute";
public void print(){
System.out.println("privateClass");
}
}
class Ab extends As{
public String ab = "extended attribute";
public void printAb(){
System.out.println("extended class");
print();
System.out.println(abc);
}
}
public static void main(String as[]){
Ab ab1 = (new pvtClass()).new Ab();
As as1 = (new pvtClass()).new As();
ab1.printAb();
as1.print();
System.out.println(as1.abc);
}
}
If you have a look at this class, I have a private class named "As" which has public attribute and public methods. I have another class named "Ab" which extends "As". I have written a main method to invoke the private attribute and methods.
below is the output for the code snippet:
extended class
privateClass
private attribute
privateClass
private attribute
There is a difference between the access of the members of a class and the access to the type itself.
public class C {
private class InnerP1 {
public void m() {
System.out.println("InnerP1.m()");
}
}
private class InnerP2 extends InnerP1 {
public void p() {
this.m();
System.out.println("InnerP2.p()");
}
}
public InnerP1 strange() {
return new InnerP2();
}
}
In this example, the interface I is visible from outside class C. The classes InnerP1 and InnerP2 are not visible from outside C. Jave itself makes not restrictions to the visibility of types you use in your public interface. The method strange() of class C returns a result of class InnerP1. Since outside of C we do not know anything about the class InnerP1 other than it is subtype of Object, the only thing we can do is use the result of strange() as an Object.
public class D {
public static void main(String[] args) {
C c = new C();
Object o = c.strange();
if(o.equals(c.strange())) {
System.out.println("Strange things are going on here!");
}
}
}
As #KnusperPudding pointed out already, the visiblity of public members is not changed, we might just not have enough knowledge of the type itself to access them.
Access to members cannot be restricted by sub-classing. When you mark a class as private then access via the class name is restricted i.e. to the same .java file, however once you have an instance of this class it can be accessed at least as easily as the super class.
I want some discussions about this, but I could not infer the answer for my case. Still need help.
Here is my code:
package JustRandomPackage;
public class YetAnotherClass{
protected int variable = 5;
}
package FirstChapter;
import JustRandomPackage.*;
public class ATypeNameProgram extends YetAnotherClass{
public static void main(String[] args) {
YetAnotherClass bill = new YetAnotherClass();
System.out.println(bill.variable); // error: YetAnotherClass.variable is not visible
}
}
Some definitions following which, the example above seems to be confusing:
1. Subclass is a class that extends another class.
2. Class members declared as protected can be accessed from
the classes in the same package as well as classes in other packages
that are subclasses of the declaring class.
The question: Why can't I access the protected member (int variable = 5) from a subclass YetAnotherClass instance (bill object)?
Classes in other packages that are subclasses of the declaring class can only access their own inherited protected members.
package FirstChapter;
import JustRandomPackage.*;
public class ATypeNameProgram extends YetAnotherClass{
public ATypeNameProgram() {
System.out.println(this.variable); // this.variable is visible
}
}
... but not other objects' inherited protected members.
package FirstChapter;
import JustRandomPackage.*;
public class ATypeNameProgram extends YetAnotherClass{
public ATypeNameProgram() {
System.out.println(this.variable); // this.variable is visible
}
public boolean equals(ATypeNameProgram other) {
return this.variable == other.variable; // error: YetAnotherClass.variable is not visible
}
}
bill is not part of the subclassed YetAnotherClass. bill is a separate YetAnotherClass.
Try int bill = this.variable; (inside a constructor) to access the subclass' members.
Your code will work if YetAnotherClass will be in the same package as ATypeNameProgram. As others wrote it won't work in other cases. Here is the working example.
package my.example;
public class MainClass extends MyAnotherClass {
public static void main(String[] args) {
MyAnotherClass bill = new MyAnotherClass();
System.out.println(bill.value); // this will work
}
}
package my.example;
public class MyAnotherClass {
protected int value = 5;
}
A class Foo can only access the protected instance members of type Bar if and only if Bar is assignable to Foo. I.e., if we can write:
Foo foo = new Bar();
For example, say we have:
package a;
public class Base {
protected int protectedField;
}
Then we can have this:
package b;
import a.Base;
public class Parent extends Base {
void foo() {
int i = this.protectedField;
}
void foo(Parent p) {
int i = p.protectedField;
}
void foo(Child c) {
int i = c.protectedField;
}
}
class Child extends Parent { }
This will compile because all protectedFields are accessed via instances of Parent. Note that because a Parent reference can be a Child instance (i.e., we can write Parent p = new Child();), we can access c.protectedField.
The following will not compile:
package b;
import a.Base;
public class Parent extends Base {
void foo(Stepchild sc) {
int i = sc.protectedField; // ERROR
}
}
class Stepchild extends Base {}
because an instance of Stepchild is not an instance of Parent.
Somewhat confusingly, this won't compile either:
package b;
import a.Base;
public class Parent extends Base {}
class Child extends Parent {
void foo(Parent p) {
p.protectedField; // ERROR
}
}
this is because a Parent object isn't a superclass or superinterface of Child, and so Child can't access its protected members.
If you ever have trouble remembering, just think of whether or not the type can be written to a reference of the type of the class. E.g., we can write:
Parent p = new Child();
but cannot write
Child c = new Parent(); // ERROR
Parent p = new Stepchild(); // ERROR
so Child won't have access to Parent's protected members, and Parent won't have access to Stepchild's protected members.
A couple final points:
Remember that protected access allows visibility among the package. In my experience, people forget this.
Finally, protected static members are always visible among the inheritance hierarchy.
You aren't creating an instance of the class that extend it, but of the parent class. Check the code below:
public class ATypeNameProgram extends YetAnotherClass{
public static void main(String[] args) {
YetAnotherClass bill = new YetAnotherClass();
System.out.println(bill.variable); // error: YetAnotherClass.variable is not visible
ATypeNameProgram a = new ATypeNameProgram();
System.out.println(a.variable); //this will work
}
}
What is the example of indirect access to private member of superclass from subclass?
A nested class has access to all the private members of its enclosing
class—both fields and methods. Therefore, a public or protected nested
class inherited by a subclass has indirect access to all of the
private members of the superclass.
Quote from http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html
In the quote, we talk about "nested" class
here is an example of how an inner class can access private fields of the outer class.
class OuterClass {
private int x = 7;
public void makeInner(){
InnerClass in = new InnerClass();
in.seeOuter();
}
class InnerClass {
public void seeOuter() {
System.out.println("Outer x is " + x);
}
}
public static void main(String[] args) {
OuterClass.InnerClass inner = new OuterClass().new InnerClass();
inner.seeOuter();
}
}
Finally, if you extend a class with the InnerClass, they will also access the private fields of the OuterClass if your InnerClass is public or protected
It is to be supposed (but the compiler does not enforce it, only warns), that a private method will end being used by a public, protected or default method (otherwise it is useless).
So, the extending class can "indirectly" call the private method by calling the public, protected or default method that ends calling the private method.
Yes, we can access private members of a superclass in the child class through the public method of the superclass which can be invoked from the child class's reference variable heaving the reference id of child class.
for example:-
class Base
{
private int x=10;
void show()
{
System.out.println(x);
}
}
class Child extends Base
{
public static void main(String... s)// public static void main(String[] args)
{
//rom jdk 1.7 main can be defined like above
Child c=new Child();
c.show();
}
}
The output will be 10
This is more of a puzzle than question. I have the following code:
public class PrivateBaseConstructor {
public static class BaseClass {
private BaseClass() {
}
}
public static class DerivedClass extends BaseClass {
public DerivedClass() {
super(); // 1*
}
}
}
Here the call for super(); at 1* is allowed even though the base class constructor is private. If we write the classes as separate classes in same package:
BClass.java
public class BClass {
private BClass() {
}
}
DClass.java
public class DClass extends BClass {
public DClass() {
super(); // 2*
}
The compiler rightly gives an error at 2* since the base class constructor is not visible.
Why doesn't the compiler throw an error in my first scenario when both the classes are declared static within one class?
if the member or constructor is declared private, then access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.
http://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.6.1
Because nested classes can see each others members. This has nothing to do with the static declarations. See the following example of your code with just nested inner classes (not static).
public class PrivateBaseConstructor {
public class BaseClass {
private BaseClass() {}
}
public class DerivedClass extends BaseClass {
public DerivedClass() {
super(); // 1*
}
}
public static void main(String[] args)
{
new PrivateBaseConstructor(). new DerivedClass();
}
}
Read more about nested classes here: http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html
Because anything declared inside a class can access its private members, including inner classes. However, if you run PMD on your class, you'll find it suggests you change the visibility of the constructor to not-private.