2013-03-07 1 views
2

В настоящее время я изучаю язык программирования Scala (люблю его кстати) и недавно обнаружил неявные преобразования. Поэтому у меня есть класс и его компаньон. и в моем объекте компаньона я хочу thees неявных преобразования:Scala неявное преобразование любого числового типа

implicit def convertToComplex(x: Double) = new Complex(x, 0); 
    implicit def convertToComplex(x: Int) = new Complex(x, 0); 
    implicit def convertToComplex(x: Float) = new Complex(x, 0); 
    implicit def convertToComplex(x: Short) = new Complex(x, 0); 
    implicit def convertToComplex(x: Long) = new Complex(x, 0); 

для того, чтобы не раздувать мой комплекс класса номера с перегрузкой на +, -, * и/для добавления типов чисел.

Так что мой вопрос:

Есть более короткий путь, чтобы написать неявные преобразования с некоторым синтаксическим сахаром сортов? (я имею в виду без всех перегрузок ...)

Заранее спасибо.

+0

Какой тип двух координат? Это исправлено, чтобы сказать 'Double', или Complex'' параметрический? Из фрагмента кода, который я собираю, это ** не ** параметрический (и поэтому он, вероятно, набирает как ** Double **, чтобы иметь возможность размещать все типы ввода), но я хотел бы получить подтверждение. –

+0

Вы думали о том, как использовать scala в цифрах? Это дает вам что-то вроде этого def plus [T: Numeric] (x: T, y: T) = x + y – Noah

+0

@ RégisJean-Gilles как реальная, так и мнимая части ** Double **. – boogie666

ответ

3

Вам нужно Integral, а не Numeric если вы хотите Complex с методом /.

Вот почти завершено решение:

scala> :paste 
// Entering paste mode (ctrl-D to finish) 

import scala.math.Integral 

class Complex[T: Integral](val real: T, val imag: T) { 
    import Integral.Implicits._ 
    def +(that: Complex[T]) = Complex(real+that.real, imag+that.imag) 
    def -(that: Complex[T]) = Complex(real-that.real, imag-that.imag) 
    def *(that: Complex[T]) = Complex(real*that.real - imag*that.imag, real*that.imag+imag*that.real) 
    def /(that: Complex[T]) = { 
    val d = that.real*that.real + that.imag*that.imag 
    Complex((real*that.real + imag*that.imag)/d, (-real*that.imag+imag*that.real)/d) 
    } 
    override def toString: String = imag.signum match { 
    case 1 => "" + real + "+" + imag +"i" 
    case -1 => "" + real + "" + imag + "i" 
    case _ => "" + real 
    } 
} 

object Complex { 
    import Integral.Implicits._ 
    def apply[T: Integral](real: T, imag: T): Complex[T] = new Complex[T](real, imag) 
    object i extends Complex[Byte](0.toByte, 1.toByte) 
    implicit class Real2Imag[T](val imag: T) { 
    def *(v: i.type)(implicit ig: Integral[T]) = Complex(ig.zero, imag) 
    } 
    implicit def promote[U, V](c: Complex[U])(implicit ev: U => V, il: Integral[V]) = 
    Complex(ev(c.real), ev(c.imag)) 
    implicit def real2complex[T: Integral](real: T) = Complex(real, implicitly[Integral[T]].zero) 
    implicit val doubleIsIntegral = scala.math.Numeric.DoubleAsIfIntegral 
} 

// Exiting paste mode, now interpreting. 

warning: there were 2 feature warnings; re-run with -feature for details 
import scala.math.Integral 
defined class Complex 
defined object Complex 

scala> import Complex._ 
import Complex._ 

scala> val c1 = 3 + 4*i 
c1: Complex[Int] = 3+4i 

scala> val c2 = 3.0 + 4.0*i 
c2: Complex[Double] = 3.0+4.0i 

scala> val c3 = c1/c2 
c3: Complex[Double] = 1.0 

scala> val c4 = 3 - 4*i 
c4: Complex[Int] = 3-4i 

scala> val c5 = c2*c4 
c5: Complex[Double] = 25.0 

Вы можете написать свой метод pow как это (Обратите внимание, как генерировать Complex один):

def pow(n: Int): Complex[T] = { 
    val one = Complex[T](implicitly[Integral[T]].one, implicitly[Integral[T]].zero) 
    Iterator.iterate(one)(_*this).drop(n).next 
    } 

scala> i.pow(2) 
res5: Complex[Byte] = -1 

scala> i.pow(10) 
res6: Complex[Byte] = -1 

scala> (1+1*i).pow(4) 
res7: Complex[Int] = -4 

scala> (1+1*i).pow(5) 
res8: Complex[Int] = -4-4i 
+0

У меня есть немного следующий за вами вопрос. Я сделал метод pow def pow (мощность: Int) = { def pow_ (что: Complex [T], iteration: Int): Complex [T] = итерационное совпадение {case 1 => that; case _ => that * pow_ (это, итерация-1); } pow_ (это, мощность); } что я должен вернуть для случая 0 (я имею в виду, как вернуть значение 1)? – boogie666

3

Вы могли бы сделать что-то вроде этого

object ConvertComplex { 
    case class Complex[T: Numeric](x: T, y: Int) { 

    val nX = implicitly[Numeric[T]] 

    def doSomething = nX.toInt(x) * y 
    def doSomethingElse = nX.plus(x, nX.fromInt(y)) 
    } 

    object Complex { 
    implicit def convertToComplect[T: Numeric](x: T) = Complex(x, 0) 
    } 

} 

и результаты испытаний:

def doSomething[T: Numeric](x: Complex[T]) = x.doSomething 
def doSomethingElse[T: Numeric](x: Complex[T]) = x.doSomething 

val double = 1: Double //> double : Double = 1.0 
val int = 1: Int   //> int : Int = 1 
val float = 1: Float  //> float : Float = 1.0 
val short = 1: Short  //> short : Short = 1 
val long = 1: Long  //> long : Long = 1 

doSomething(double)  //> res0: Int = 0 
doSomething(int)   //> res1: Int = 0 
doSomething(float)  //> res2: Int = 0 
doSomething(short)  //> res3: Int = 0 
doSomething(long)   //> res4: Int = 0 

doSomethingElse(double) //> res5: Double = 1.0 
doSomethingElse(int)  //> res6: Int = 1 
doSomethingElse(float) //> res7: Float = 1.0 
doSomethingElse(short) //> res8: Short = 1 
doSomethingElse(long)  //> res9: Long = 1 
+1

Вы можете сделать свой код более красивым, добавив следующий импорт: 'import nX._'. Это позволит вам заменить 'nX.plus (x, nX.fromInt (y))' на 'x + fromInt (y)'. Также я думаю, что 'y' должен быть типа' T' –

+0

Я не думал об импорте, хороший! Я хочу сделать второй аргумент определенным типом, чтобы показать свойства преобразования «Числовые», в реальной реализации я полностью согласен. – EECOLOR

0

Да, есть. Я предполагаю, что класс Complex имеет параметры Double. Затем вы можете написать неявное преобразование одним выстрелом.

implicit def doubleToComplex[T <% Double](x: T): Complex = new Complex(x, 0)