Scala Метод на Generi c Тип данных - PullRequest
0 голосов
/ 06 февраля 2020

Я пытаюсь создать обобщенный c класс, который принимает только java .math.BigDecimal или Long. Вот код:

class myClass[T]()
{ 
    def display( x : T) = {
      println(x.doubleValue())
    }
}


val input = new java.math.BigDecimal(100)
// val input = 100L

val x = new myClass[java.math.BigDecimal]()
x.display(input)

Ясно, что у меня будет эта ошибка: ScalaFiddle. scala: 22: ошибка: значение doubleValue не является членом параметра типа T.

Я пытался игра с неявным преобразованием, просмотром и контекстом в течение нескольких часов. Результата пока нет. Можно ли заставить Scala поверить мне, что у T есть метод .doubleValue ()? (java .big.Decimal и Long оба имеют метод .doubleValue (), но у них нет общего суперкласса)

Ответы [ 3 ]

3 голосов
/ 06 февраля 2020

Попробуйте связать структурный тип

class myClass[T <: {def doubleValue(): Double}]

или тип класса

trait HasDoubleValue[T] {
  def doubleValue(t: T): Double
}
object HasDoubleValue {
  implicit val long: HasDoubleValue[Long] = t => t.doubleValue
  implicit val bigDecimal: HasDoubleValue[BigDecimal] = t => t.doubleValue
}

implicit class DoubleValueOps[T: HasDoubleValue](x: T) {
  def doubleValue(): Double = implicitly[HasDoubleValue[T]].doubleValue(x)
}

class myClass[T: HasDoubleValue]
2 голосов
/ 06 февраля 2020
scala> class C private (n: Number) {
     | def this(i: Long) = this(i: Number)
     | def this(b: BigDecimal) = this(b: Number)
     | def d = n.doubleValue
     | }
defined class C

scala> new C(42L).d
res0: Double = 42.0

scala> new C(BigDecimal("123456789")).d
res1: Double = 1.23456789E8

или с параметром типа

scala> class C[A <: Number] private (n: A) { def d = n.doubleValue ; def a = n } ; object C {
     | def apply(i: Long) = new C(i: Number) ; def apply(b: BigDecimal) = new C(b) }
defined class C
defined object C
2 голосов
/ 06 февраля 2020

В Dotty (Scala 3) мы можем использовать типы объединения , для пример ,

class myClass[T <: (Long | java.math.BigDecimal)]() { 
  def display(x: T) = 
    println(
      x match {
        case t: Long => t.doubleValue
        case t: java.math.BigDecimal => t.doubleValue
      }
    )
}

new myClass().display(new java.math.BigDecimal(100))   // OK
new myClass().display(100L)                            // OK
new myClass().display("100")                           // Error
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...