

以下に示したコードの様にJavaをKotlinで置き換えてみましたが、コメントアウトを外すとコンパイルエラーになります。

Javaの方が長いので、おそらくJava風？なKotlinのコードになってしまっているかもしれませんが、どこに原因があると思われますでしょうか？

* * *

**元のJavaコード**

[code]

    class Super {
       static String x = "Super : x";
       String y = "Super : y";
       static void methodA() {
           System.out.println("Super : methodA()");
       }
       void methodB() {
           System.out.println("Super methodB()");
       }
    }
    class Sub extends Super {
       static String x = "Sub : x";
       String y = "Sub : y";
       static void methodA() {
           System.out.println("Sub : methodA()");
       }
       void methodB() {
           System.out.println("Sub : methodB()");
       }
    }
    class Sample {
       public static void main(String[] args) {
            Super obj = new Sub();
            System.out.println(obj.x);
            System.out.println(obj.y);
            obj.methodA();
            obj.methodB();
       }
    }
    
    
[/code]

**Kotlinで置き換えたコード**

[code]

    open class Super {
         open val y: String = "Super : y"
    
         companion object {
              val x: String = "Super : x"
    
              fun methodA() {
                    println("Super : methodA()")
              }
         }
    
         open fun methodB() {
               println("Super : methodB()")
         }
    }
    class Sub : Super() {
          override val y: String = "Sub : y"
    
          companion object {
               val x: String = "Sub : x"
    
               fun methodA() {
                     println("Sub : methodA()")
               }
          }
    
          override fun methodB() {
                println("Sub : methodB()")
          }
    }
    fun main(args: Array<String>) {
           val obj: Super = Sub()
           //println(obj.x)
           println(obj.y)
           //obj.methodA()
           obj.methodB()
    }
    
    
[/code]


CC BY-SA 4.0
2019-07-22T14:22:27.617
56820
2019-07-23T00:25:29.773
2019-07-23T00:25:29.773
3060
question
java kotlin
JavaのコードをKotlinのコードに置き換えたい


そもそも元のJavaコードが「こんなコードを書くと一見奇妙な結果が出る」書き方の例になっています。

  * 隠蔽フィールドの宣言

Javaでは、サブクラス側のフィールドは親クラス側のフィールドを隠すような別フィールドになる。コンパイラは「コンパイル時に見えている側」のフィールドを使う。

  * `static`メンバーのインスタンスからの呼び出し

Javaではコンパイル時に決まる型を元にしてどのクラスの`static`メンバーを使うか決められる。

いずれも現在のJavaコンパイラでは警告が出るはずです。これらの警告を無視しないようにしましょう。

* * *

Kotlinでは、そのような誤用を防ぐため、そもそも同様のことは出来ないようになっています。

  * フィールドを直接宣言できない

Kotlinのプロパティ宣言はJavaで言うと、フィールドとgetterとsetterをまとめて宣言しているようなものです。従って、メソッドと同様にオーバライドもでき、メソッドのオーバライドと同様の挙動になります。

  * `static`なメンバーは定義できない

Kotlinの`companion`は「特定のクラスに結びついた別オブジェクトのプロパティやメソッド」を宣言するためのものです。`static`の代替とみなされていますが、Javaの`static`と完全に同じ動作をするわけではなく、インスタンスを通じては呼び出せません。

無理やりコンパイルが通るように書くと、こんな感じになるでしょう。

[code]

    fun main(args: Array<String>) {
           val obj: Super = Sub()
           println(Super.x)
           println(obj.y)
           Sub.methodA()
           obj.methodB()
    }
    
[/code]

上記のように`Super`か`Sub`を明示しないと呼び出せないので、Javaのように「`Sub`側のプロパティやメソッドが参照されると思ったら`Super`の方だった」なんてことは起こりません。

* * *

KotlinはJavaと相互運用できるよう考えられていますが、「文法が違うだけでJavaと全く同じ」なのではありません。ご質問にあるJavaコードのように「時に期待と異なる一見奇妙な結果が出る」ようなコードの挙動を完全に再現することは出来ません。


CC BY-SA 4.0
2019-07-22T18:28:53.157
56821
2019-07-22T18:47:34.750
2019-07-22T18:47:34.750
13972
13972
56820
answer