問題
Base、及びそれを継承しているDerivedがあります。
Base.java
public class Base {
protected String message = "Base";
public String inspect() {
return "I'm " + message;
}
}
Derived.java
public class Derived extends Base {
public Derived() {
super.message = "Derived";
}
}
Derived#inspect()を呼び出した時、I'm cracked
と表示させるにはどうすれば良いか?
- リフレクションは使わない
- Base, Derivedはもちろん変更しない
- 異なるパッケージにファイルを追加して対応する
Test.java
public class TestA {
public static void main(String[] args) {
Derived derived = new Derived();
derived.message = "cracked";
// ^これはmessageが見えないのでエラーになる
System.out.println(derived.inspect());
}
}
解答
こんな感じで、Baseを継承したCrackerクラスを用意。
その中のメソッドで置き換えます。
Cracker.java
public class Cracker extends Base {
public void crackDerived(Derived derived) {
derived.message = "hacked";
}
}
Test.java
public class TestA {
public static void main(String[] args) {
Derived derived = new Derived();
Cracker cracker = new Cracker();
cracker.crackDerived(derived);
System.out.println(derived.inspect());
}
}
結論
- Javaのアクセス修飾子はインスタンス単位ではなくクラス単位。
- 継承関係が兄弟関係にあるクラスでもprotectedフィールドが見える。
- なんで?