Как работает метод расширения в Kotlin? - PullRequest
1 голос
/ 06 августа 2020

В Java вы не можете расширить конечный класс, но в Kotlin вы можете написать метод расширения для таких конечных классов. Как они заставили его работать внутри компании? Я не смог найти ни одной статьи, объясняющей внутреннюю работу Kotlin методов расширения.

Ответы [ 2 ]

3 голосов
/ 06 августа 2020

Если вам интересно, как код Kotlin превращается в код Java, есть способ взглянуть на это. IntelliJ обеспечивает декомпилирование байт-кода Kotlin в код Java. Вы можете найти его Tools -> Kotlin -> Show Kotlin Bytecode и нажать Decompile. Затем будет показан код Java.

Вот пример.

Kotlin

val Int.asByteArray get() =
    byteArrayOf(
            (this shr 24).toByte(),
            (this shr 16).toByte(),
            (this shr 8).toByte(),
            this.toByte())

val Int.asHex get() = this.asByteArray.asHexUpper

@ExperimentalUnsignedTypes
val ByteArray.asInt get() =
        ((this[0].toUInt() and 0xFFu) shl 24) or
        ((this[1].toUInt() and 0xFFu) shl 16) or
        ((this[2].toUInt() and 0xFFu) shl 8) or
        (this[3].toUInt() and 0xFFu)

Java

public final class IntExtensionKt {
   @NotNull
   public static final byte[] getAsByteArray(int $this$asByteArray) {
      return new byte[]{(byte)($this$asByteArray >> 24), (byte)($this$asByteArray >> 16), (byte)($this$asByteArray >> 8), (byte)$this$asByteArray};
   }

   @NotNull
   public static final String getAsHex(int $this$asHex) {
      return HexExtensionKt.getAsHexUpper(getAsByteArray($this$asHex));
   }

   /** @deprecated */
   // $FF: synthetic method
   @ExperimentalUnsignedTypes
   public static void asInt$annotations(byte[] var0) {
   }

   public static final int getAsInt(@NotNull byte[] $this$asInt) {
      Intrinsics.checkParameterIsNotNull($this$asInt, "$this$asInt");
      byte var1 = $this$asInt[0];
      boolean var2 = false;
      int var5 = UInt.constructor-impl(var1);
      short var6 = 255;
      boolean var3 = false;
      var5 = UInt.constructor-impl(var5 & var6);
      byte var7 = 24;
      var3 = false;
      var5 = UInt.constructor-impl(var5 << var7);
      byte var8 = $this$asInt[1];
      var3 = false;
      int var9 = UInt.constructor-impl(var8);
      short var10 = 255;
      boolean var4 = false;
      var9 = UInt.constructor-impl(var9 & var10);
      byte var11 = 16;
      var4 = false;
      var9 = UInt.constructor-impl(var9 << var11);
      var3 = false;
      var5 = UInt.constructor-impl(var5 | var9);
      var8 = $this$asInt[2];
      var3 = false;
      var9 = UInt.constructor-impl(var8);
      var10 = 255;
      var4 = false;
      var9 = UInt.constructor-impl(var9 & var10);
      var11 = 8;
      var4 = false;
      var9 = UInt.constructor-impl(var9 << var11);
      var3 = false;
      var5 = UInt.constructor-impl(var5 | var9);
      var8 = $this$asInt[3];
      var3 = false;
      var9 = UInt.constructor-impl(var8);
      var10 = 255;
      var4 = false;
      var9 = UInt.constructor-impl(var9 & var10);
      var3 = false;
      return UInt.constructor-impl(var5 | var9);
   }
}

Как видите, метод расширения Kotlin превратился в метод public final static в final class в Java.

3 голосов
/ 06 августа 2020

В Java вы не можете расширить конечный класс, но в Kotlin вы можете написать метод расширения для таких конечных классов

Я думаю, вы предполагаете, что методы расширения использовали наследование, которое не является. Это скорее статический c метод, замаскированный под kotlin синтаксис c сахар. Например, посмотрите на приведенный ниже простой метод расширения:

String.removeSpace(): String {
    return this.replace(" ", "")
}

Вы можете рассматривать его как эквивалент следующего java кода.

static String removeSpace(String input) {
    return input.replace(" ", "")
}

Что делает kotlin, вот оно предоставляет оболочку сверху, так что, используя this, вы можете получить экземпляр вызывающего. Объединив это с возможностью Kotlin определять функцию как первоклассный гражданин, вы можете написать такую ​​элегантную вещь:

fun String.removeSpace() = this.replace(" ", "")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...