4

ソースコードがわかっているクラスの関数を置き換えたい。問題は、関数がプライベートであるためにオーバーライドできないことと、クラスを拡張して機能全体をオーバーライドできないことです。これは、考えられるすべてのコンストラクターに不正な呼び出しがあるためです。

今、私は完全に迷子になっています。私はその望ましい機能をどのように実装できるかわかりません(Android VideoViewコントロールのコントロール、別名MediaControllerのテーマ)。関数をリフレクションなどに置き換える方法はありますか?それとも、スーパークラスのコンストラクターではなく、スーパースーパークラスと呼ぶことは可能ですか?

これが私の問題を示す非常に基本的なクラスです:

public class Base {
    public Base(int state) {
        // must be called
    }
}
public class Example extends Base {
    public Example(int state, boolean bla) {
        super(state);
        badCall();
    }        
    public Example(int state) {
        this(state, false);
    }
    private badCall() {
        // doing bad things
    }
}

Exampleまた、クラスを単純にコピーできないように、のインスタンスが必要であることに注意してください。

4

3 に答える 3

2

これは、モック フレームワーク (jmockit) を使用した不自然な例です。出力は次のとおりです。

元の私的方法
その他の方法
新しい私的方法
その他の方法

public static void main(String[] args) {
    A a = new A(); //prints Original private method
    a.m2(); //prints Some other method

    new MockUp<A>() {

        @Mock
        public void m() {
            System.out.println("New private method");
        }
    };

    A b = new A(); //prints New private method
    b.m2(); //prints Some other method
}

static class A {

    public A() {
        m();
    }

    private void m() {
        System.out.println("Original private method");
    }

    public void m2() {
        System.out.println("Some other method");
    }
}
于 2013-01-03T08:18:50.973 に答える
2

プライベート メソッドにアクセスするためにAspectJを使用できます。

public privileged aspect SomeClassExposerAspect {

  void around(SomeClass obj) : execution(private void badCall()) {        
       try {
          // use privileged access to return the private member
          ((Example )obj).badCall();
       }
       // safeguard against unexpected 3rd party library versions, if using load-time weaving
       catch (NoSuchMethodError e) {
          //log something
       }
   }
  }
}

これについての素敵なブログがあります。

于 2013-01-03T08:24:37.600 に答える
1

ソースがある場合は、クラスに「パッチ」を適用することをお勧めします。

変更したバージョンをコンパイルしてビルドし、jar 内の古いバージョンを置き換えるか、クラス パスの前の方に追加して、古いバージョンを非表示にします。

ところで: この方法で JVM のクラスにパッチを適用することもできますが、これが良い考えであることはめったにありません。;)

于 2013-01-03T09:00:06.270 に答える