3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Scalaで日時の範囲を表すクラス群をつくる

Last updated at Posted at 2019-11-11

Scalaで日時の範囲を表すクラス群をつくる

きっかけ

Javaで開発をしていて、日時の範囲を表すクラスがなかったので少し不便に感じました。java.time.Periodjava.time.Durationは範囲というより2点間の距離に関心があるクラスなので違うんですよね。
よく使いそうなので私的メモとして残しておきます。

基底クラス

本筋とはそれますが、java.time.LocalXxxのラッパーも用意しました。始端、終端をラッパークラスにするイメージです。

日時を表すTrait

継承先クラスは型引数で受け取り、内部で保持する値の型はtypeで受け取るというダブルスタンダードになりました。継承先クラスの情報を型引数で受け取っている理由は、Orderedを継承する際に型引数を指定する必要があったからです。この型に大小関係がなければ、この型を始端と終端にした範囲という概念があり得ないと考えたのでTraitでOrderedを継承しました。

Chronology.scala
trait Chronology[ClassType <: Chronology[_]] extends Ordered[ClassType]{
  type ValueType //LocalTimeとかが指定される想定

  val value: ValueType

  def isAfter(other: ClassType): Boolean

  def isEquals(other: ClassType): Boolean

  final def isAfterOrEqual(other: ClassType): Boolean = isAfter(other) || isEquals(other)

  def isBefore(other: ClassType): Boolean

  final def isBeforeOrEqual(other: ClassType): Boolean = isBefore(other) || isEquals(other)
}

範囲を表すTrait

日時の型を受け取り、受け取った型を始端と終端にもつTraitです。
始端と終端の大小関係を事前条件として指定しています。

ChronologyRange.scala
trait ChronologyRange {
  type ChronologyType <: Chronology[_]

  type ClassType <: ChronologyRange

  val start: ChronologyType

  val end: ChronologyType

  require(start <= end)

  def overlaps(other: ClassType): Boolean
}

使い方

例:Date

Date.scala
case class Date(value: LocalDate) extends Chronology[Date] {
  override type ValueType = LocalDate
  def toInstant: Instant = value.atStartOfDay(ZoneId.systemDefault()).toInstant

  def isAfter(other: Date): Boolean = value.isAfter(other.value)

  def isBefore(other: Date): Boolean = value.isBefore(other.value)

  override def isEquals(other: Date): Boolean = value.isEqual(other.value)

  override def compare(that: Date): Int = value.compareTo(that.value)
}
DateRange.scala
case class DateRange(start: Date, end: Date) extends ChronologyRange {
  override type ChronologyType = Date
  
  override type ClassType = DateRange

  override def overlaps(other: DateRange): Boolean = ???
}

学び

  • Traitにもフィールドを宣言できること
  • Traitにもイニシャライザを書けること
  • Orderedを継承したクラスのインスタンス同士を不等号で比較できること

あとで調べること

  • typeとtype parameterってどう違うの
  • TraitとAbstract Classってどう使い分けるの
3
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?