How to Access Outer Class from an Inner Class

Getting hold of the outer class object from the inner class object

Within the inner class itself, you can use OuterClass.this. This expression, which allows to refer to any lexically enclosing instance, is described in the JLS as Qualified this.

I don't think there's a way to get the instance from outside the code of the inner class though. Of course, you can always introduce your own property:

public OuterClass getOuter() {
return OuterClass.this;
}

EDIT: By experimentation, it looks like the field holding the reference to the outer class has package level access - at least with the JDK I'm using.

EDIT: The name used (this$0) is actually valid in Java, although the JLS discourages its use:

The $ character should be used only in
mechanically generated source code or,
rarely, to access pre-existing names on
legacy systems.

How to access outer class from an inner class?

The methods of a nested class cannot directly access the instance attributes of the outer class.

Note that it is not necessarily the case that an instance of the outer class exists even when you have created an instance of the inner class.

In fact, it is often recommended against using nested classes, since the nesting does not imply any particular relationship between the inner and outer classes.

How can I access OuterClass field from InnerClass?

Simply by doing OuterClass.this and the name of the field from the OuterClass that you want to access, for instance OuterClass.this.OuterName. In your code would look like the following:

public class OuterClass {
public String name; // field which has same name
public OuterClass(String name) {
this.name = name;
}
public class InstanceInnerClass {
public String name; // field which has same name
public InstanceInnerClass(String name) {
this.name = name;
}
public void printAllName() {
// What should be written in this code
// to print both name fields from OuterClass and InnerClass
System.out.printf("OuterName: %s, InnerName: %s\n", name, OuterClass.this.name);
}
}
}

When you have two fields with the same name one in the inner class and the other on the outer class (i.e., shadowing), and you try to access from the inner class that field, the compiler assumes that you want to access the field from the inner class, and ignores the other from the outer class. Otherwise, it would be impossible to choose, which variable to use.

Shadowing

If a declaration of a type (such as a member variable or a parameter
name) in a particular scope (such as an inner class or a method
definition) has the same name as another declaration in the enclosing
scope
, then the declaration shadows the declaration of the enclosing
scope. You cannot refer to a shadowed declaration by its name alone.

How to access outer class member from an inner class in Python?

The problem with your code is that you didn't understand correctly the meaning of name mangling, that's exactly what you're doing when adding the double leading score in your variable name.

When setting up the variable as self.__x, what you're actually doing is telling the world outside your class that it can only be accessed this way when operating inside the Outer class. If you try to access outside, lets say add after the definition of obj the following print(obj.__x), you'll see the same problem.

The name mangling means that when accessing the variable outside of the scope of your class, you should call the variable _ClassName__variableName, so, in our example, you should use print(obj._Outer__x) to be able to print the variable.

Since your Inner class works the same way, as an outside scope, the simplest solution would be to rewrite your display method this way:

def display(self):
print("str_in : ", self.__str_in)
print("Inside display() of Inner Class")
print("x : ", self.outer._Outer__x)
print("str : ", self.outer._Outer__str)
self.outer.fn()

Now, other thing I noticed, and can generate problems if you didn't do this consciously, is the call self.i1 = self.Inner(Outer()). Here you're not using the same object data that you instantiated as obj, but creating a new instance of Outer and sending this to Inner.

And what's the problem with this?
Let's say you added the following lines:

obj = Outer()
obj._Outer__x = 10
obj.show()

Then the output of your show() will always be x: 20, because this change you've done in the variable, was made to an instance that was not passed to Inner.

If it's not the behaviour you were aiming for, just change this line to:

self.i1 = self.Inner(self)

So now you're effectively passing the instantiated object to Inner

Accessing outer-class fields through inner-class instance from outer-class

Why can't I access the outer classes field through an instance of
inner class in outer class in line 8?

Because the field is a field of the class OuterClass and not of the class InnerClass. So to access it, you need an instance of the class OuterClass, not of the class InnerClass.

Sure, inside InnerClass definition, you can implicitly access all the fields of OuterClass. But that's only a matter of access from inside this context. You're not specifying what is the object of which you're trying to access the field, so the language automatically selects that for you. It's usually this.field, but in the case of a field from the containing class, it's actually OuterClass.this.field.

Once you're trying to indicate what is the object of which you're trying to access a field, rather than let the language implicitly select that object for you, well this object must actually be of the class that contains the field.

Accessing the outer class when inheriting from it

In your example, you created two objects - an instance of Parent, and an instance of Child.

Parent().Child()
^ ^
| |
1 2

So there is really only two different things that you can access from the init block of B. You can either access the Parent object using this@A, which is the object associated with the Child object, or the Child object itself using this (or redundantly this@B).

"Accessing the outer class", which presumably you mean A, is not something you can do, because there is not even such an instance of A.

You can however, invoke A's implementations of methods/properties using super@B.xxx (note that it is not super@A. Read it as "super of B"). Perhaps this is what you intended on doing in the first place.

For example, changing A to the following:

abstract class A {

override fun toString() = "A"

abstract inner class B : A() {
init {
println("Should display 'Parent': ${super@B.toString()}")
}
}
}

would print "A".

Note that this actually calls toString on the Child object, not the Parent object. You cannot do the same to the Parent object, because it is a different object. This init is creating the Child object, right?

In summary, this accesses some object that is in scope. super accesses a specific implementation of a method/property up the inheritance hierarchy.

In Ruby, how can inner class access variables/methods defined in outer class?

In Ruby, how can inner class access variables/methods defined in outer class?

Ruby does not have a concept of "inner" or "outer" classes. It sounds like you are coming from a language like BETA, Scala, or Newspeak, but Ruby is not BETA, Scala, or Newspeak. As a general rule, any programming language works exactly how the specification for the programming language says it works, not how the specification for some other programming language says it works. BETA, Scala, and Newspeak have nested classes, but Ruby has not.

In Ruby, you can lexically nest a class definition, but that does not create a nested class. If you nest the definition of a class inside the definition of another class, that does not create any sort of relationship whatsoever between those two classes. None. You cannot "access variables/methods" of one class from the other class because there is no relationship between those two classes you could follow in order to get at those variables/methods.

The only thing a nested class definition does, is namespace the constant defined by the inner class definition to the outer class. That's it. There is no relationship between the two classes, the only relationship is between the constant and the class.

It is just not possible.

The way to create relationships between classes in Ruby is inheritance, not nesting (because there is no nesting). The way to create relationships between objects in Ruby is association, aggregation, or composition, not nesting.

Ruby is flexible enough to implement something that behaves like a "proper" BETA-style inner class. Remember, an inner class is "nested" inside an object instance of the outer class. We can emulate that using an instance variable:

class Outer
attr_reader :Inner

def outer_method
__callee__
end

private

attr_writer :Inner

def initialize
self.Inner = Class.new(self.class) do
def inner_method
[__callee__, outer_method]
end
end
end
end

outer = Outer.new
inner = outer.Inner.new
p inner.inner_method

Please note that I made the inner class inherit from the outer class: that is the way to do behavior sharing in Ruby. You need to have some form of inheritance or association relationship. The nesting does not create a relationship.



Related Topics



Leave a reply



Submit