开发者

Call method from instance

开发者 https://www.devze.com 2023-04-10 20:46 出处:网络
Let\'s say I have two classes, A and B, in turn have some methods, something() and nothing() and an instance of B is created in A, as

Let's say I have two classes, A and B, in turn have some methods, something() and nothing() and an instance of B is created in A, as

public class A {

    public A() {
        B b = new B();
        b.nothing();
    }

    public void something() {
        ...
    }
}

A calling b.nothing() is all standard stuff, but is there any means which by instance b can call a.something(), assuming the instance of 开发者_运维问答A is called a. If not, why is this conceptually wrong?


I don't think there's anything conceptually wrong with this.

However, for the mechanics to work, b needs to know which instance of A to call something() on. For this, either B's constructor, or its nothing() method, needs to take an A reference as an argument.

example 1:

public class B {
  public void nothing(A a) {
    ...
    a.something();
    ...
  }
}

example 2:

public class B {
  private final A a;
  public B(A a) {
    this.a = a;
  }
  public void nothing() {
    ...
    this.a.something();
    ...
  }
}

example 3:

There is a third way, applicable in some circumstances. If B is an inner class of A, it has an implicit reference to its associated instance of A.

public class A {
  public void something() { ... }
  public class B {
      public void nothing() {
        ...
        something();
        ...
      }
  }

}


is there any means which by instance b can call a.something()

You can't get hold of the caller in a method so, no, there's no way to do that.

If not, why is this conceptually wrong?

Two issues come to my mind immediately:

  • What would the type of the caller be? Since anyone could call b.nothing(), you can't assume more than that it's an Object which would result in lots of ugly down casts.

  • The implementation of b.nothing() shouldn't care about who's calling him. What happens if you refactor A and move the call to b.nothing() to some other class? It would be quite surprising if b.nothing() all of a sudden stopped working.


The only way b.nothing() can call a.something() is if you tell the instance of B about the instance of A. For example:

b.nothing(this);

where B.nothing looks like:

public void nothing(A a)
{
    // Do other stuff
    a.something();
}

Alternatively, you could pass in this in the constructor to B, which would keep hold of the reference:

B b = new B(this);
b.nothing();

Note that letting this escape during a constructor call is generally a bad idea - you're letting B.nothing() call A.something() on an object which isn't fully initialized yet - its constructor hasn't finished executing. That can lead to undesirable and hard-to-diagnose behaviour sometimes.


To do this, b would require a reference to a. There are two ways to provide that:

  1. Pass such a reference in the constructor of B or give B an appropriate setter.
  2. If B is an inner class of A, then it has such a reference implicitly.
0

精彩评论

暂无评论...
验证码 换一张
取 消