Intereting Posts
Оборонительная копия изменчивой коллекции в классе данных Kotlin Авторизация Spotify Code отклоняется за плохие учетные данные, несмотря на то, что отправлен действительный токен Как подавить проверку орфографии на константе строки в Android Kotlin? Тестирование JUnit в Android Studio с Kotlin прекратило работать FirebaseRecyclerAdapter – populateViewHolder не получает доступ к данным Android Studio бросает java.lang.ClassNotFoundException при запуске кода Kotlin Не иметь доступа к контроллеру Spring boot, но иметь доступ к index.html Ошибка Kotlin при преобразовании из Java-кода Тесты для Android выполняются без lanuching эмулятора (не отображается диалоговое окно устройства) – пустой набор тестов Сравните класс данных в Kotlin без ID Android Kotlin не может использовать list.sort () с lambda Унаследованные декларации платформы сталкиваются при расширении класса Java в Котлине Скрипт Kotlin не может получить доступ к ресурсам META-INF (persistence.xml) из jar Как настроить Mockito для Kotlin и Android Android Kotlin – Невозможно планировать уведомление для будущей даты с помощью диспетчера аварийных сигналов

Альтернативы полем бокса или расширению ВСЕХ строк в Котлине?

Учитывая, что в Kotlin нельзя создавать подклассы встроенных типов, я ищу способ добавить специальные функции метода к определенным типам строковых полей в записи, не применяя эти функции расширения ко всем строкам (даже в пределах этого типа записи). Скажем, например, у меня есть некоторые изменяемые строковые поля внутри записи, для которых я хочу определить поведение с особыми целями.

class Customer { // ... var zipcode: String var email: String // ... } 
  • Предположим, что для thisCustomer.zipcode.plusFour я хотел бы назвать thisCustomer.zipcode.plusFour чтобы получить +4 почтового индекса (99999-9999) через регулярное выражение.
  • Для email предположим, что я хотел бы иметь возможность вызвать thisCustomer.email.domain чтобы иметь регулярное выражение, чтобы получить … @ company.com часть указанного thisCustomer.email.domain электронной почты.

Мои цели заключаются в следующем:

  1. Избегайте накладных расходов во время выполнения class Zipcode бокса в class Zipcode с помощью всего лишь одного var внутри, учитывая, что размер набора записей клиентов может быть миллионным.
  2. Избегайте синтаксиса необходимости присваивать thisCustomer.zipcode.value = "99999-9999" или thisCustomer.zipcode = Zipcode("99999-9999") , если мне пришлось thisCustomer.zipcode = Zipcode("99999-9999") строку.
  3. Избегайте добавления общих String.plusFour расширения String.plusFour и String.domain , даже в пределах класса Customer … потому что zipcodes и электронные письма могут технически вызывать расширения друг друга

Я об этом подумал и рассмотрел следующие варианты, но с каждым ударил:

  • subclassing String: невозможно, так как строки (и все встроенные) закрыты
  • применение интерфейса Zip к объявлению var ( var zipcode: String, Zip ): Нет такого синтаксиса, который я мог бы найти
  • добавление внутренних функций внутри самого геттера: синтаксис, похоже, не существует для этого
  • используя объекты или функции внутри функций: не мог придумать, как это работает, хотя я, возможно, недостаточно изобретателен

Я пропустил здесь очевидное решение? Даже если это не очевидно, со всей синтаксической магией Котлина, есть ли способ сделать это возможным? Может быть, есть способ выполнить некоторые / все цели выше, не используя ни один из этих подходов?

Вы можете использовать псевдонимы типов, чтобы сделать намерение понятным:

 typealias ZipCode = String val ZipCode.plusFour get() = ... typealias Email = String val Email.domain get() = ... class Customer { // ... var zipcode: ZipCode var email: Email // ... } 

К сожалению, это только уточняет намерения и не мешает компилятору разрешить zipcode.domain . Но пока я не думаю, что есть какой-то способ, который удовлетворяет обеим задачам 1 и 3.

Разработчики Kotlin решили не поддерживать псевдонимы типа присваивания-несовместимости, которые соответствовали бы всем вашим требованиям, в пользу ожидания классов значений, доступных на JVM, как описано в https://github.com/Kotlin/KEEP/issues / 4 .

Вы можете создать класс декоратора, используя делегат:

 class YourString(val value: String) : Comparable<String> by value, CharSequence by value { val plusFour: String get() = "" //your logic here val domain: String get() = "" //your logic here override fun toString() = value } 

Применение:

 fun String.toYourString() = YourString(this) class Customer(var zipCode: YourString, var email: YourString) val customer = Customer("+4 99999-9999".toYourString(), "xxx@company.com".toYourString()) println(customer.zipCode.plusFour) println(customer.email.domain)