2011-10-31 11 views
7

Mam następujące klasy:Scala: dwa niejawny argument, z tym samym oświadczeniem

class Example(implicit doSomething1: (Double, Double) => Double, implicit doSomething2: (Double, Double) => Double) 
{ 
    //.. 
} 

Jak widać konstruktor ma dwa argumenty (ukryte funkcje) o tej samej deklaracji. Ale chcę "wstrzyknąć" dwie różne definicje. Czy jest to możliwe w sposób niejawny? Czy jest to możliwe tylko w znany jawny sposób?

Dzięki

Odpowiedz

0

Zapis

class Example(implicit doSomething1: (Double, Double) => Double, doSomething2: (Double, Double) => Double) 
{ 
    //.. 
} 

Ale jeśli dwie ukryte argumenty mają ten sam typ, będą oczywiście mieć taką samą wartość (nadal można przekazać różne argumenty wprost).

8

Jeśli kompilator poszukuje implicit (Double, Double) => Double w ukrytym zakresie, albo jest dokładnie jeden o wyższym priorytecie i wybierze ten jeden raz, albo nie ma (albo nie ma go wcale w ukrytym zakresie, albo więcej niż jeden o najwyższym priorytecie) i wystąpi błąd z powodu braku ukrytej wartości.

Jeśli chcesz się rozróżnić, możesz mieć dwa różne typy, oba rozszerzające funkcję2 [podwójne, podwójne, podwójne]. Na przykład:

trait Addition extends Function[Double, Double, Double] 
trait Multiplication extends Function[Double, Double, Double] 
class Example(implicit addition: Addition, implicit multiplication: Multiplication) 

To może być w porządku, warto wybrać obie operacje niezależnie. Jeśli dwa wybory muszą być conistent, może to więcej sensu mieć tylko jedną cechę zarówno działania

trait Ring { 
    def add(x: Double, y: Double): Double 
    def mult(x: Double, y: Double): Double 
} 
// or `case class Ring(
//  addition: (Double, Double) => Double, 
//  multiplication: (Double, Double) => Double) 
class Example(implicit ring: Ring) 

Wreszcie, wszystko to ma sens tylko, jeśli uzyska odpowiednie działania w zakresie niejawny „naturalnie”. Jeśli musisz zrobić, aby były ukryte za każdym razem, gdy tworzysz przykład, jak na przykład, możesz równie dobrze być jednoznacznym, jak na przykład.

Ponadto, jeśli oczekuje większość połączeń do pracy o tej samej wartości, a chcesz tylko zmienić niektóre z nich, można raczej pójść na argumenty z domyślnymi wartościami

class Example(doSomething1 : (Double, Double) => Double = <default value>, doSomething2 ...) 

Można nawet mieć oba, domyślny argument z wartością domyślną. Jeśli to zrobisz, wartość domyślna zostanie użyta, gdy nie zostanie znaleziony żaden niejawny.

Powiązane problemy