Я хотел бы немного лучше понять две функции ниже. Я знаю, что он очень компактен и более или менее понимаю, что он делает: он преобразует каждый символ строки в строку «0» и «1». Но...
Как точка (перед encodeToByteArray) соединяет «s» с encodeToByteArray()?
Где я могу найти больше информации о том, что обозначает точка?
Кроме того, как и почему код { byte -> binaryStringOf(byte) }
может работать в этом месте?
Откуда он «знает», что есть байт, с которым он вызывает функцию binaryStringOf(byte)
Где я могу найти больше информации об этом?
fun binaryStringOf(message: String): String {
var s: String
s = (message)
.encodeToByteArray()
.joinToString("") { byte -> binaryStringOf(byte) }
return s
}
fun binaryStringOf(b: Byte): String {
return b.toString(2).padStart(8, '0')
}
.encodeToByteArray()
работает с входящей строкой (в данном случае message
). Он возвращает a ByteArray; так что-то, что представляет собой массив значений Byte.
И для этого объекта массива он вызывает метод joinToString(). Этот метод получает различные аргументы, но предоставляется только строка-разделитель (""
) и параметр transform
.
Теперь: transform
— это функция. Это то, что можно вызывать с параметрами и что должно возвращать определенный результат.
Ключевая часть, которую нужно понять, заключается в том, что { byte -> ... }
— это transform
параметр функции.
Вышеупомянутое форматирование делает вещи немного более запутанными, но позвольте мне попытаться объяснить, что происходит.
=
— это оператор присваивания. В нем говорится: «присвоить переменную s
результату выражения в правой части».
Теперь мы видим, что message
является параметром в binaryStringOf
функции типа String
. String
— это класс , который содержит функцию (также называемую методом, если она является членом класса) с именем encodeToByteArray
, которая возвращает ByteArray.
ByteArray
, в свою очередь, имеет функцию с именем joinToString
, которой мы задаем два параметра: один типа String
и один типа ((Byte) -> CharSequence)
(т. е. сама функция передается как переменная с использованием лямбда-синтаксиса). В Kotlin есть синтаксический сахар, чтобы это выглядело лучше, когда лямбда является последним аргументом.
Итак, утверждение
s = (message)
.encodeToByteArray()
.joinToString("") { byte -> binaryStringOf(byte) }
означает, что «переменной s
присваивается значение, полученное в результате вызова joinToString
в результате вызова encodeToByteArray
в message
.
Затем return s
говорит, что возвращаемое значение из binaryStringOf
должно быть тем значением, которое было присвоено s
.
Как может «байт» в {byte -> binaryStringOf(byte)} идентифицировать каждый байт в byteArray, созданном .encodeToByteArray()?
Лямбда, которая передается в joinToString
, выполняется для каждого байта ByteArray. Например, это похоже на вызов forEach
в списке. Вы можете добиться того же результата, используя цикл for
для каждого байта в byteArray.
Просмотр исходного кода может помочь прояснить ситуацию. github.com/JetBrains/kotlin/blob/master/libraries/stdlib/common/…joinToString
вызывает более общий joinTo
, который имеет цикл for (element in this)
, который вызывает преобразование для каждого элемента (через buffer.append(transform(element))
)
На данный момент нет, может быть, позже у меня будет больше объяснений.