When I tried to understand how to work with collections in java, I realised that I don't understand how polymorphism works for inner classes.
Simple code example:
class Parent {
public static void main(String[] args) {
new Parent().newInnerClass().myMethod();
new Child().newInnerClass().myMethod();
}
public I newInnerClass() {
return new InnerClass();
}
private final class InnerClass implements I {
#Override
public void myMethod() {
System.out.println("parent inner class");
foo();
}
}
public void foo() {
System.out.println("foo from parent");
}
}
class Child extends Parent {
public void foo() {
System.out.println("foo from child");
}
}
interface I {
void myMethod();
}
result:
parent inner class
foo from parent
parent inner class
foo from child
Therefore first link affects the third method invocation. It is surprising to me.
Initially I thought that needed methods selected accordind to the link. But new Parent().newInnerClass() and new Child().newInnerClass() are links to InnerClass from Parent.
Can you clarify my misunderstanding?
P.S.
If InnerClass was in Child and extended InnerClass from Parent - this behaviour wouldn't be surprising for me.
There are no special rules for polymorphism in inner classes.
Inner class differs from regular class in two things:
Inner class holds an implicit reference to its containing object
Inner class can access private methods of its containing class (not relevant here)
That's how you can rewrite your example without inner class:
class Parent {
...
public I newInnerClass() {
return new NotInnerClass(this);
}
...
}
class NotInnerClass implements I {
private final Parent containingObject;
public NotInnerClass(Parent containingObject) {
this.containingObject = containingObject;
}
#Override
public void myMethod() {
System.out.println("parent inner class");
containingObject.foo();
}
}
This code produces the same output as your, because when you invoke
new Child().newInnerClass().myMethod();
containingObject is a Child and containingObject.foo() is a regular polymorphic call.
When you use inner class, compiler does the same thing behind the scenes.
Related
I have parent class and a child class, both of having a method m1 with same signature (Override), can I call parent class method in following scenario. I dont want to change child class method.
// Super class
public class Parent
{
public void m1()
{
System.out.println("Parent method");
}
}
// Sub class
public class Child extends Parent {
#Override
public void m1() {
System.out.println("Child method");
}
}
// User class
public class Kavi {
public static void main(String[] args) {
Parent p = new Child();
p.m1();
}
}
I want to call parent class m1 method. I know that I can use super in child class method to call its parent method. but I have no right to change the source code of child class. and I have to call it from child class object. please anybody help !!! is it possible in java ??
While creating the Object you are using reference of Super class but your object is of child class, so while calling m1() method the overrided method will be invoked. If you want the method of the super class to be invoked then object should be of Super class. As :
Parent parent=new Parent();
parent.m1();
OR
you can invoke the super class m1() method from the child class.
#Override
public void m1() {
super.m1();
System.out.println("Child method");
}
OR ELSE
import java.lang.reflect.*;
class A {
public void method() {
System.out.println("In a");
}
}
class B extends A {
#Override
public void method() {
System.out.println("In b");
}
}
class M {
public static void main( String ... args ) throws Exception {
A b = new B();
b.method();
b.getClass()
.getSuperclass()
.getMethod("method", new Class[]{} )
.invoke( b.getClass().getSuperclass().newInstance() ,new Object[]{} ) ;
}
}
Without changing the code, you can't do this. You're essentially talking about p.super.m1() which isn't legal in Java. If you want your parent to act like a parent, don't make it a child.
If both parent and child are stateless, you could create a facade over them and explicitly manage the state; this would work, but I wouldn't recommend it.
public class Facade extends Parent {
public enum State {PARENT, CHILD};
private final Child delegate;
private State state = State.CHILD;
public Facade(Child delegate) {
this.delegate = delegate;
}
#Override
public void m1() {
if (State.CHILD == state) {
delegate.m1();
} else {
super.m1();
}
}
public void setState(State state) {
this.state = state;
}
}
This is a purely academic exercise - I can't think of a single good reason to do this in the real world. If you're using an OO language, don't fight the OO paradigm!
I think it not possible. There are two ways to call a parent class method
1.) crate object of parent class as
Parent p = new Parent();
2.) Use super in child class method as
#Override
public void m1() {
super.m1();
System.out.println("Child method");
}
Apart from the already mentioned way, you can declare both the methods as static.
so when you do this
Parent p = new Child();
p.m1();
the static method of parent class would be called and the output will be "Parent method"
Note : The static keyword in Java means that the variable or function is shared between all instances of that class as it belongs to the type, not the actual objects themselves.
So if you have a variable:
private static int i = 0; and you increment it ( i++ ) in one instance, the change will be reflected in all instances.
If you can not use super then instead of creating the child class object you can directly use
Parent p = new Parent();
p.m1();
if you can't even modify the code inside main method then I think it's not possible .
So here's the scenario.
I have a class A, and I want some of its methods to behave differently depending on how the class is called.
What I've done now is something like this:
interface Interface{
public void someMethod();
}
class A{
int variable;
Interface getA1(){
return new A1();
}
Interface getA2(){
return new A2();
}
class A1 extends A implements Interface{
public void someMethod(){
variable++;
}
}
class A2 extends A implements Interface{
public void someMethod(){
variable--;
}
}
}
Now the problem with this is that when getA1() or getA2() is called, it will actually return a completely new instance of A1, or A2, where the int variable is totally separate to the parent class A (duh, silly me of course thats how it works).
So the question is. Is it possible in java to return some kind of inner class that allows you to modify the data within the outer class through it's methods?
The key thing is having a single class that can return interfaces that modify that single class in different ways, depending on which method was used to create that interface.
I might be overlooking something simple here, sorry but it's got me stumped! :(
Edit: I think the better way of explaining it is - I want to give direct access to local variables, to a subclass (or another class), and have a method in the original class that can create the other class.
EDIT2: The reason why it created a separate instance when getA1()/getA2(), is likely because class A1 and A2 were declared to extend A. It seems like if the extends clause is removed, then it works as expected.
Yes an anonymous class would do e.g.
interface Interface{
public void someMethod();
}
public class A {
int variable;
Interface getA1() {
return new Interface() {
#Override
public void someMethod() {
variable++;
}
};
}
}
It should be pointed out though that this is equivalent to declaring non-static inner classes albeit more concise.
First of all, I find it very strange that your inner classes are extending the outer class. I can't think of a good reason to do that and I'm not exactly sure what that even does.
Besides that, I don't understand your issue. All inner classes have access to their parent class's fields. For example, the following:
public class Tester {
private int myInt;
public InnerTester getInnerTester() {
return new MyInnerTester();
}
public InnerTester getOtherInnerTester() {
return new OtherInnerTester();
}
public interface InnerTester {
public void doStuff();
}
public class MyInnerTester implements InnerTester{
#Override
public void doStuff() {
myInt++;
}
}
public class MyOtherInnerTester implements InnerTester {
#Override
public void doStuff() {
myInt++;
}
}
public static void main(String[] args) {
Tester tester = new Tester();
System.out.println("Before: " + tester.myInt);
tester.getInnerTester().doStuff();
tester.getOtherInnerTester().doStuff();
System.out.println("After: " + tester.myInt);
}
}
outputs:
Before: 0
After: 2
However, this all seems pretty shady. I'm not exactly sure why you would want to take advantage of this behavior. I've done similar things with action listeners before, but I wouldn't exactly call their parent object an "ActionListenerFactory". Why don't you just have a method to increment the field on the object itself?
I need to refactor class extracting abstract superclass.
E.g.
UpperClass {
NestedClass {
UpperClass.this.someMethod();
}
}
Like:
AbstractUpperClass {
NestedClass {
?????.this.someMethod();
}
}
After I plan inherit AbstractUpperClass in 2 classes UpperClass1 and UpperClass2.
But I don't know how to refactor this inner class because it inovokes method of enclosing class. Does it possible?
Thanks.
The trick here is knowing how the inner class works. It's essentially just a "normal", static class, but whose constructor implicitly gets a reference to the enclosing class. So, this:
public class TopLevel {
public void go() {
new Inner().bar();
}
public void foo() { }
public class Inner {
public void bar() {
TopLevel.this.foo();
}
}
}
is equivalent to this:
public class TopLevel {
public void go() {
new Inner(this).bar(); // explicitly passing in "this"
}
public void foo() { }
public static class Inner {
private final TopLevel parent; // note that we have this new field
public Inner(TopLevel parent) { // note this new constructor
this.parent = parent;
}
public void bar() { // we use the explicit reference instead
parent.foo(); // of the implicit TopLevel.this
}
}
}
So, with all that said, the way to refactor your inner class to be a top-level class is to add an explicit field referencing the UpperClass instance, and passing this reference into the NestedClass constructor. In other words, be like that second code snippet instead of the first.
I'm not sure if my question title describes my situation aptly, so my apologies if it doesn't! Anyway, let's say I have the following code snippet (visibility is as stated):
public class ChildClass extends ParentClass {
// more code
private void myMethod() {
MyClass mine = new MyClass() {
public void anotherMethod() {
// insert code to access a method in ParentClass
}
};
}
}
Is it possible for code within anotherMethod() to access a protected method found in ParentClass? If so, how can this be done?
I've tried something like...
(ParentClass.this).parentMethod();
...but obviously it doesn't work due to scope issues.
This compiles fine:
class MyClass {
}
class ParentClass {
protected void parentMethod() {
}
}
class ChildClass extends ParentClass {
private void myMethod() {
MyClass mine = new MyClass() {
public void anotherMethod() {
parentMethod(); // this works
}
};
}
}
A non-static inner class can access all methods of the enclosing class as if it were it's own methods:
public class Test {
public int getOne() {
return 1;
}
public class Inner {
public int getEnclosingOne() {
return getOne(); // this works...
}
}
}
A static inner class can not, as a static inner class is not bound to an instance of the parent class. That can only call static methods on the enclosing class.
As for methods when taking into account inheritance, an method in a non-static inner class can use all the methods of the enclosing (outer) class.
The interesting part is Test2.super.getOne() which indeed obtains getOne() from Test2.super, which is a Test. This is just like Test2 would access the method, namely using super though prefixed with Test2 to indicate you're accessing the namespace of the outer class.
public class Test2 extends Test {
public int getInnerOuterParentOne() {
Inner2 inner2 = new Inner2();
return inner2.getOuterParentOne();
}
public int getInnerOuterOne() {
Inner2 inner2 = new Inner2();
return inner2.getOuterOne();
}
public int getOne() {
return 2;
}
public class Inner2 {
public int getOuterOne() {
return getOne();
}
public int getOuterParentOne() {
return Test2.super.getOne();
}
}
public static void main(String[] args) {
Test2 test2 = new Test2();
System.out.println(test2.getInnerOuterOne()); // 2
System.out.println(test2.getInnerOuterParentOne()); // 1
}
}
There is no way to access "parent class method" in Java, irrelatively to visibility (except for super.parentMethod() in subclass's parentMethod()).
That is, if ChildClass overrides parentMethod(), there is no way to call ParentClass.parentMethod() (bypassing ChildClass.parentMethod()) from other methods of ChildClass.
However, if ChildClass doesn't override parentMethod(), that method is inherited by ChildClass, so that you can access it as a ChildClass's method, i.e. simply as parentMethod().
I'm think perhaps there is not a way to do this, but I thought it worth asking. I want to do something like the following:
public class Super {
public static String print() { System.out.println(new Super().getClass().getSimpleName()); }
public Super() {}
}
public class Subclass extends Super {
public Subclass() {}
public void main(String[] args) {
Super.print();
Subclass.print();
}
}
My hope is to get the Super.print() to show "Super" and Subclass.print() to show "Subclass". I don't see how to do this from a static context however. Thanks for the help.
I'm well aware that I can do this without static methods, and that I can pass a class into each method call. I don't want to do that as that requires redefining several static methods on many subclasses.
You can simply define a separate Subclass.print() method with the desired implementation. Static methods are class scoped, so every subclass can have its own implementation.
public class Subclass {
public Subclass() {}
public static String print() {
System.out.println(Subclass.class.getSimpleName());
}
public void main(String[] args) {
Super.print();
Subclass.print();
}
}
Note that your code can be somewhat simplified - Super.class suffices instead of new Super().getClass().
Also note, that static methods are not polymorphic - Super.print() and Subclass.print() will always call the method in the respective class. This is why they are bound to a class, not an object.
If you have a large class hierarchy, you may end up with a lot of duplicated code by implementing a separate static print() in each. Instead, you could define a single non-static method to do the job:
public abstract class Super {
public final String print() {
System.out.println(this.getClass().getSimpleName());
}
...
}
Note that this method does not even need to be polymorphic - this.getClass() will always return the actual subclass token.
Note also that I declared Super as abstract - this is (almost always) good practice to follow with base classes.
You can do this with out using static methods
public class Parent {
public print(){
System.err.println(this.getSimpleName());
}
}
public class Child extends Parent {
public void main(String[] args) {
Parent p = new Parent();
p.print();
Child c = new Child();
c.print();
}
}