2012-06-30 16 views
8

Chyba rozumiem nowej „klasy wartość” cechę Scala 2.10, w porównaniu z Haskell za newtype:Jak wyglądają zdefiniowane przez użytkownika klasy wartości z Java?

trait BoundedValue[+This] extends Any { this: This => 

    def upperBound: This 

    def lowerBound: This 

} 

class Probability @throws(classOf[IllegalArgumentException]) (v: Double) extends AnyVal with BoundedValue[Probability] { 

    val value: Double = if ((v >= 0.0) && (v <= 1.0)) v else throw new IllegalArgumentException((v.toString) + "is not within the range [0.0, 1.0]") 

    override val upperBound: Probability = new Probability(0.0) 

    override val lowerBound: Probability = new Probability(1.0) 

    // Implement probability arithmetic here; 
    // will be represented by Double at runtime. 

} 

Mam pytanie jest, w jaki sposób klasa wartość wydaje się kod Java, który używa pakietu Scala w którym jest zadeklarowany? Czy klasa wartości pojawia się jako klasa odniesienia po stronie Java, czy też jest całkowicie wymazana (i dlatego pojawia się jako typ, który jest zawijany)? Innymi słowy, w jaki sposób bezpieczne dla typów są klasy wartości, gdy Java jest zaangażowana na poziomie źródłowym?


EDIT

Powyższy kod nie będzie kompilować, zgodnie z SIP-15 dokumentu (połączonego w odpowiedzi Daniela), ponieważ klasy wartości nie mogą mieć żadnej logiki inicjalizacji, ponieważ albo v musi być jawnie wartością val lub Probability musi mieć metodę unbox i odpowiednią metodę box na swoim obiekcie towarzyszącym, a ponieważ klasy wartości muszą mieć dokładnie jedno pole. Prawidłowy kod to:

trait BoundedValue[This <: BoundedValue[This]] extends Any { this: This => 

    def upperBound: This 

    def lowerBound: This 

} 

class Probability private[Probability] (value: Double) extends AnyVal with BoundedValue[Probability] { 

    @inline override def upperBound: Probability = new Probability(0.0) 

    @inline override def lowerBound: Probability = new Probability(1.0) 

    @inline def unbox: Double = value 

    // Implement probability arithmetic here; 
    // will be represented by Double at runtime (mostly). 

} 

object Probability { 

    @throws(classOf[IllegalArgumentException]) 
    def box(v: Double): Probability = if ((v >= 0.0) && (v <= 1.0)) new Probability(v) else throw new IllegalArgumentException((v.toString) + "is not within the range [0.0, 1.0]") 

} 

Samo pytanie jest jednak nadal aktualne.

+1

W swoim programie testowym, czy byłeś w stanie wypchnąć zawiniętą wartość poza prawidłowe granice z Java? –

+0

@DavidHarkness Nie mam teraz dostępu do komputera z 2.10.0-M4, więc nie wiem. Sprawdzę, kiedy będę mógł. –

Odpowiedz

6

Klasy wartości kompilują się jako normalne klasy i mogą być wyświetlane jako referencje.

Magia w nich jest taka, że ​​, gdy klasa wartości nie wymyka się zakresowi, wszystkie jej ślady są usuwane z kodu, skutecznie podkreślając cały kod. I oczywiście daje dodatkowe bezpieczeństwo typu.

Zobacz także SIP-15, który wyjaśnia mechanikę.

+0

Dziękujemy! Myślałem, że przeczytałem SIP, ale chyba nie. –

+2

Równie interesującym pytaniem, jak "w jaki sposób typy wartości Scala są zakodowane na platformie, która sama nie ma typów wartości (np. JVM)" jest "w jaki sposób typy wartości Scala są zakodowane na platformie, która * ma * same typy wartości (np. CLI) ". Na przykład, czy typy wartości Scala można skompilować do struktur w interfejsie CLI? Czy jest zagwarantowane, że będą * zawsze * kompilowane do struktur? –

+1

Twoje pytanie jest bardzo interesujące, ale zdałem sobie sprawę, że nie tylko struktury CLI nie są obsługiwane (nie były wymienione w SIP, ostatnio czytałem je), ale prawdopodobnie są również bezużyteczne. Klasy wartości mogą mieć tylko jedno pole, jako nowe typy Haskella, więc myślę, że używanie struktur, a nie prymitywów, nie pomogłoby. Struktury mają wiele zalet w zakresie wykorzystania pamięci - ale aby z nich korzystać, należy zapewnić osobny mechanizm, to znaczy adnotację z żądaniem takiego zachowania, które można zignorować. Problem semantyczny polega na tym, że struktury powinny prawdopodobnie dziedziczyć z AnyVal tylko w CLI, a nie w JVM. – Blaisorblade

Powiązane problemy