Каков правильный способ работы с полями в Котлине?

Как я должен правильно обрабатывать перенос из класса Java с полями в Котлин?

Несколько чтений в документах Котлина показывают, что их классы не могут определять поля внутри них. Будучи повстанцем, которым я являюсь, на самом деле пытаюсь преобразовать свой существующий Java-код в его коллега Котлин (с использованием Java-конвертера Java Studio для Kotlin), также отмечает «поля» с неприятно ослепительной подсветкой .

Это мой класс Java:

public final class PaperDay implements Day { private Date date; private Weather weather; PaperDay() { // Obligatory empty ctor for Paper. } PaperDay(Date date) { this.date = truncateTimeFromDate(date); this.weather = Weather.SUNNY; // Default to SUNNY, 'cos sunny is good! } PaperDay(Date date, Weather weather) { this.date = truncateTimeFromDate(date); this.weather = weather; } private Date truncateTimeFromDate(Date date) { Calendar calendar = Calendar.getInstance(); calendar.setTime(date); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); ... 

.. и это похоже на то, что он преобразуется в .kt:

введите описание изображения здесь

Как я могу сделать это путь Котлин?

Я предполагаю, что вы хотите что-то вроде этого:

 class PaperDay (private var date: Date, private var weather: Weather = Weather.SUNNY) : Day { init { this.date = truncate(date) } private fun truncateTimeFromDate(date1: Date): Date { return date1 } } 

Вы должны стараться использовать необязательные параметры ( var weather: Weather = Weather.SUNNY ), где бы вы ни находились, поскольку это повышает удобочитаемость.

Чтобы избежать (несколько уродливого) блока init вы также можете передать только одно из двух свойств в качестве параметра конструктора (спасибо Jayson Minard) и вычислить другое свойство в его объявлении с помощью «нормального» параметра:

 class PaperDay (dateWithTime: Date, private val weather: Weather = Weather.SUNNY): Day { private val date: Date = truncateTimeFromDate(dateWithTime) ... } 

Обратите внимание, что это также использует val вместо var поскольку неизменяемость обычно является лучшим вариантом.

Если вам нужен и пустой конструктор, вы можете добавить это (хотя я не думаю, что это хорошая практика, и это показатель для «плохого» дизайна:

  constructor() : this(Date()) 

В качестве альтернативы добавление значения по умолчанию для всех параметров в конструкторе также неявно создает пустой конструктор.

если вы действительно хотите, чтобы значение nullability определяло ваши свойства ? , Например:

 class PaperDay (private var date: Date?, private var weather: Weather? = Weather.SUNNY) 

вы также можете изменить другой конструктор на constructor() : this(null)


Кроме того, IMHO также неплохо добавить метод truncate... как функцию расширения для класса Date вместо того, чтобы взламывать его в этом классе:

 fun Date.truncateTimeFromDate() { Calendar calendar = Calendar.getInstance() calendar.setTime(this) calendar.set(Calendar.HOUR_OF_DAY, 0) calendar.set(Calendar.MINUTE, 0) ... } 

Подобно @Lovis, но избегая использования var который должен быть «последним средством»:

 class PaperDay (dateWithTime: Date = Date(), private val weather: Weather = Weather.SUNNY): Day { private val date: Date = truncateTimeFromDate(dateWithTime) private fun truncateTimeFromDate(dateWithTime : Date) : Date { ... } } 

В этой версии конструктор имеет один параметр, который не является свойством класса, а другой является свойством. Позже в классе класса свойство объявляется и устанавливается на усеченную дату.

Если у вас есть значение по умолчанию для каждого параметра конструктора, Kotlin автоматически создаст конструктор по умолчанию, который использует эти значения по умолчанию. Не нужно добавлять его отдельно.

Если ваша инфраструктура должна создавать экземпляр с конструктором по умолчанию, а затем устанавливать значения после факта, вы хотите сделать что-то более похожее на следующее и вернуться к использованию var :

 class PaperDay (dateWithTime: Date = Date(), private var weather: Weather = Weather.SUNNY): Day { private var date: Date = truncateTimeFromDate(dateWithTime) set(value) { field = truncateTimeFromDate(value) } private fun truncateTimeFromDate(dateWithTime : Date) : Date { return dateWithTime } } 

Теперь мы гарантировали, что у нас никогда не будет недопустимой даты, хранящейся в этом свойстве, с помощью настраиваемого сеттера.

Если вы хотите взаимодействовать для всех вариантов конструктора, доступных на Java, вы можете использовать аннотацию @JvmOverloads для конструктора для генерации других перестановок с использованием значений параметров по умолчанию.

И как указывает @Lovis, переместите truncateTimeFromDate в функцию расширения в классе Date . Он может быть локальным для файла, для модуля, для класса, и во всех этих случаях он будет читать лучше.