处理Kotlin领域的正确方法是什么?

时间:2016-02-17 14:23:45

标签: java kotlin

如何正确处理从具有字段的Java类到Kotlin的迁移?

对Kotlin的文档进行了一些阅读,发现他们的课程不能在其中定义字段。作为我的反叛者,实际上尝试将我现有的Java代码转换为其Kotlin对应物(使用Android Studio的Java到Kotlin转换器功能)也标志着"字段"使用unpleasantly blinding highlight

这是我的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:

enter image description here

我怎么能以Kotlin方式做到这一点?

2 个答案:

答案 0 :(得分:4)

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

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,因为不变性通常是更好的选择。

如果你还需要空构造函数,你可以添加它(虽然我不认为这是一个很好的做法,它是"坏&#34的指标; 设计:

 constructor() : this(Date())

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

如果您真的希望可空性使用?定义您的属性。 E.g:

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

然后您也可以将其他构造函数更改为constructor() : this(null)

此外,它的恕我直言也是一个好主意,将truncate...方法添加为Date类的extension function,而不是在此类中添加它:

fun Date.truncateTimeFromDate() {
  Calendar calendar = Calendar.getInstance()

  calendar.setTime(this)

  calendar.set(Calendar.HOUR_OF_DAY, 0)
  calendar.set(Calendar.MINUTE, 0)
  ...
}

答案 1 :(得分:3)

与@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 annotation来生成使用默认参数值的其他排列。

正如@Lovis指出的那样,将truncateTimeFromDate移动到Date类的扩展函数。它可以是文件,模块,类的本地,在所有这些情况下,它将更好地读取。