スーパークラスとサブクラスのフィールドはどれが呼び出しされるのか??
java silverの問題を解いているとスーパークラスとサブクラスのフィールドではどれが呼び出されるのかがわからなかったから再確認
パターンがいろいろと多いのでまずは例になるコードを置いておきます。
package system.source;
public class Main{
public static void main(String[] args){
FrenchDog french = new FrenchDog();
FrenchDog japanese_french = new JapaneseDog();
JapaneseDog japanese = new JapaneseDog();
System.out.println(french.kind);//french
System.out.println(japanese_french.kind);//french
System.out.println(japanese.kind);//japanese
french.showKind();//french
japanese_french.showKind();//japanese
japanese.showKind();//japanese
french.say();//buhi
japanese_french.say();//buhi
japanese.say();//buhi
System.out.println(japanese.owner);//sho
french.who();//sho
japanese_french.who();//sho
japanese.who();//sho
}
}
interface Animal {
default void showName(String name){
System.out.println("my name is"+name+"(interface method)");
}
default void showAge(int age){
System.out.println("my age is "+age+"(interface method)");
}
}
interface Dog extends Animal{
@Override
default void showName(String name ) {
System.out.println("my name is "+name+"(Dog method)");
}
}
class FrenchDog implements Dog{
public String kind="french";
public String say="buhi";
public String owner = "sho";
public void showKind(){
System.out.println("FrenchDog:"+kind);
/*super.showKind(kind); */
}
public void say(){
System.out.println("FrenchDog:"+say);
}
public void who(){
System.out.println("owner:"+owner);
}
}
class JapaneseDog extends FrenchDog{
public String kind = "japanese";
public String say="wan";
@Override
public void showKind(){
System.out.println("JapaneseDog:"+kind);
}
@Override
public void who(){
System.out.println("owner:"+owner);
}
}
//コンパイル・実行・出力結果
PS C:\practice_javasilver> javac -d classFiles system/source/Main.java
PS C:\practice_javasilver> java -cp classFiles system.source.Main
french
french
japanese
FrenchDog:french
JapaneseDog:japanese
JapaneseDog:japanese
FrenchDog:buhi
FrenchDog:buhi
FrenchDog:buhi
sho
owner:sho
owner:sho
owner:sho
ここからが説明になります。少しだけメソッドのオーバーライドの話も入っていくのでわからずらいです。
■スーパークラスにスーパークラスのインスタンスを格納
・インスタンス名.フィールド名で呼び出し→スーパークラスのフィールド
・メソッド内でフィールドの呼び出し→スーパークラスのフィールド
(メソッドもスーパークラスのものが呼び出される)
■スーパークラスにサブクラスのインスタンスを格納
・インスタンス名.フィールドの呼び出し→スーパークラスのフィールド
(フィールド名が重複している場合は格納しているデータ型(箱)に
のっとって使用するフィールドが決まる)
・メソッド内でフィールドの呼び出し(オーバーライド済み)
→サブクラスのフィールド(メソッドが呼び出されたクラスのものに従う)
・メソッド内でフィールドの呼び出し(オーバーライドなし)
→スーパークラスのフィールド(〃スーパークラスのものが呼び出しされるため)
■サブクラスにサブクラスのインスタンスを格納
・インスタンス名.フィールドの呼び出し→サブクラスのフィールド
・メソッド内でフィールドの呼び出し(オーバーライド済み)
→サブクラスのフィールド(メソッドが呼び出されたクラスのものに従う)
・メソッド内でフィールドの呼び出し(オーバーライド無し)
→サブクラスのフィールド(〃)
■サブクラスにサブクラスのインスタンスを格納(サブクラスにフィールド定義なし)
・変数名.フィールドの呼び出し→スーパークラスのフィールド
・メソッド内でのフィールドの呼び出し(オーバーライド済み)
→スーパークラスのフィールド
・メソッド内でフィールドの呼び出し(オーバーライドなし)
→スーパークラスのフィールド
※注意点
フィールドについてはメソッドと動作が違い呼び出しされたクラスのメソッドに依存してそのクラスのフィールドが呼び出しされる。そのため単純にフィールドだけの呼び出しとメソッドを介して呼び出しするのでは動作が変わってくるため注意しましょう。
また、サブクラスに同じ変数名のフィールドが定義されていない場合はコンパイルエラーになるよりも先にスーパークラスで定義されているフィールドが呼び出しされます!!
難しいなぁと思ったので繰り返し活用して理解を深めていこうと思います~