2017-03-08 3 views
2

Ich bin neu in Scala und ich möchte eine generische Klasse schreiben, die Operatoren überladen. Aber ich möchte die Typen auf Int, Long und Double beschränken. Ist es möglich, eine obere Typgrenze für primitive Typen zu erstellen?Scala oberen Typ Grenzen für primitive Typen

Hier ist, was ich für Int getan habe. Ich muss diese Klasse generisch machen und sie sollte nur Int, Long und Double akzeptieren. Wenn dies nicht der richtige Ansatz ist, hoffe ich, dass jemand eine alternative Lösung für das Problem geben kann.

class MyClass(value: Int) { 
    def +(operand: Int): MyClass = { 
    return new MyClass(value+operand); 
    } 

    def -(operand: Int): MyClass = { 
    return new MyClass(value-operand); 
    } 

    def *(operand: Int): MyClass = { 
    return new MyClass(value*operand); 
    } 

    def /(operand: Int): MyClass = { 
    return new MyClass(value/operand); 
    } 
} 

Antwort

3

Sie könnten die Type Class Pattern verwenden. Ich würde eine implizite MyClassOperators[T] in Geltungsbereich benötigen, und implementieren Sie es nur für die gewünschten Int, und Double.

das Merkmal definieren die Durchführung der Operationen:

lässt
object MyClassImplicits { 
    trait MyClassOperators[T <: AnyVal] { 
    def +(firstOperand: T, secondOperand: T): MyClass[T] 

    def -(firstOperand: T, secondOperand: T): MyClass[T] 

    def *(firstOperand: T, secondOperand: T): MyClass[T] 

    def /(firstOperand: T, secondOperand: T): MyClass[T] 
    } 

nun eine konkrete Umsetzung für Int bieten:

implicit object MyClassIntOperators extends MyClassOperators[Int] { 
    override def +(firstOperand: Int, secondOperand: Int): MyClass[Int] = new MyClass[Int](firstOperand + secondOperand) 

    override def -(firstOperand: Int, secondOperand: Int): MyClass[Int] = new MyClass[Int](firstOperand - secondOperand) 

    override def *(firstOperand: Int, secondOperand: Int): MyClass[Int] = new MyClass[Int](firstOperand * secondOperand) 

    override def /(firstOperand: Int, secondOperand: Int): MyClass[Int] = new MyClass[Int](firstOperand/secondOperand) 
} 

und die Definition von MyClass ändern, um die impliziten MyClassOperators[T] zu sein in ihrem Umfang zu verlangen:

class MyClass[T <: AnyVal : MyClassOperators](val value: T) { 
    def doSomeAddition(otherValue: T): MyClass[T] = { 
     implicitly[MyClassOperators[T]].+(value, otherValue) 
    } 
} 

Wenn wir laufen diese mit einem Int Beispiel:

def main(args: Array[String]): Unit = { 
    val myClassOfInt = new MyClass[Int](1) 
    println(myClassOfInt.doSomeAddition(2).value) 
} 

Ausbeuten:

3 

Aber wenn wir versuchen, dies mit einer Double Instanz (die noch nicht implementiert):

[error] could not find implicit value for evidence parameter of type tests.NewTest.MyClassImplicits.MyClassOperators[Double] 
[error]  val myClassOfInt = new MyClass[Double](1.0) 
[error]      ^
[error] one error found 
+0

Vielen Dank. Dies scheint eine sehr gute Lösung zu sein. Ich werde es versuchen und überprüfen und diese Antwort akzeptieren. –

+0

Es funktioniert wie vorgesehen. Danke noch einmal. –

Verwandte Themen