什么是对付Kotlin领域的正确方法?

我应该如何处理从具有字段的Java类到Kotlin的迁移?

对Kotlin的文档的一些阅读揭示了他们的类不能在其中定义字段。 作为我的反叛者,实际上试图将我现有的Java代码转换成与Kotlin相对应的(使用Android Studio的Java到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:

在这里输入图像描述

我怎样才能做到这一点Kotlin的方式?

我假设你想要这样的东西:

 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),并使用“normal”参数计算其声明中的其他属性:

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

请注意,这也是使用val而不是var因为不变性通常是更好的选择。

如果你还需要有空的构造函数,你可以添加这个(虽然我不认为这是一个好的做法,这是一个“坏”设计的指标:

  constructor() : this(Date()) 

或者,在构造函数中为所有参数添加一个默认值也会隐式地创建一个空的构造函数。

如果你真的想要可空性定义你的属性使用? 。 例如:

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

你也可以将其他的构造函数改为constructor() : this(null)


此外,恕我直言也是一个好主意,作为Date类的扩展函数添加truncate...方法,而不是在这个类中:

 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类的扩展函数中。 它可以是文件,模块,类的本地,在所有这些情况下,它会读得更好。