2012-02-27 11 views
5

Na przykład muszę uzyskać dostęp do manifestu w funkcji def a[A:ClassManifest], aby uzyskać klasę usuwania. Mogę użyć funkcji Predef.implicitly, ale w takim przypadku mój kod będzie tak długi, jak jeśli użyję pełnego formularza def a[A](implicit b:ClassManifest[A]). Czy są też wygodne generowane nazwy dla tych niejawnych argumentów?Jak uzyskać dostęp do niejawnego "ukrytego", tj. Def a [A: B] lub def a [A <% B]?

+1

Zawsze można zadeklarować metodę o mniejszej nazwie, ale nie należy _nie polegać na magicznych nazwach generowanych przez Scalac. –

Odpowiedz

5

Istnieją trzy predefiniowane metody Predef że zrobi to za Manifest s, ClassManifestOptManifest s i s: manifest[T], classManifest[T] i optManifest[T], odpowiednio. Możesz napisać własne "implicit getters" dla innych klas typów według tego samego wzorca. Oto na przykład manifest[T]:

def manifest[T](implicit m: Manifest[T]) = m 

Więc oto jak można pisać własne:

trait UsefulTypeclass[A] { 
    def info = 42 // sample method 
} 

// the “implicit getter” 
def usefulTypeclass[A](implicit tc: UsefulTypeclass[A]) = tc 

// a method that uses the implicit getter 
def foo[A: UsefulTypeclass] = 
    usefulTypeclass[A].info 
+2

Jako schludny trik: jeśli nazwiesz niejawny getter "apply" i umieścisz go na obiekcie towarzyszącym UsefulTypeclass, możesz użyć "UsefulTypeclass [T]" jako wartości reprezentującej wystąpienie typu T bez potrzeby importowania niczego więcej niż sama czcionka. –

+0

@RM Dobra sztuczka. Sądzę, że musiałby to być 'UsefulTypeclass [T]()' (z dodatkowym '()'). –

+0

Właściwie to nie potrzebuje parens. Jeśli masz (wybacz brak formatowania) obiekt TC {def zastosuj [T] (niejawny x: TC [T]) = x} możesz dosłownie wywołać go z "TC [SomeClass]", ponieważ definiowane jest "apply" jako metoda bez parametrów z niejawną listą parametrów, a [SomeClass] rozróżnia ją tylko od odwołania do obiektu TC. Odradza się do TC.apply [SomeClass] (theImplicitValue) –

0

scalap na ratunek!

Wziąłem ten kod:

object TestThing extends App { 
    def one { println("one") } 
    def two[T] { println("two") } 
    def three[T : Manifest] { println("three") } 
    def four[T: Manifest, U : Manifest] { println("four") } 
} 

i prowadził ją przez scalap. Oto co mam:

object TestThing extends java.lang.Object with scala.App with scala.ScalaObject { 
    def this() = { /* compiled code */ } 
    def one : scala.Unit = { /* compiled code */ } 
    def two[T] : scala.Unit = { /* compiled code */ } 
    def three[T](implicit evidence$1 : scala.Predef.Manifest[T]) : scala.Unit = { /* compiled code */ } 
    def four[T, U](implicit evidence$2 : scala.Predef.Manifest[T], evidence$3 : scala.Predef.Manifest[U]) : scala.Unit = { /* compiled code */ } 
} 

Jak widać, pierwsze niejawna Oczywisty jest nazywany evidence$1. Drugi i trzeci-choć w innym zakresie! - nazywane są evidence$2 i evidence$3. Więc ... w ten sposób nawiązujesz do Manifestów.

Mimo to wydaje mi się nieco przerażające, że usunięcie manifestu, który znajduje się wyżej w klasie, spowoduje zmianę nazwy manifestu znajdującego się niżej w pliku. Podobnie nie pomaga również to, że podświetlanie składni wtyczki IntelliJ Scala wydaje się uważać, że zmienne Manifesta w zakresie są evidence$1 i evidence$2 i nie sądzi się, że evidence$3 jest tam ważną zmienną (nawet jeśli jest, i evidence$1 nie jest). Ogólnie rzecz biorąc, może te rzeczy powinny być brane pod uwagę jako znaki ostrzegawcze o graniu z ukrytymi zmiennymi Manifest?

+2

Z pewnością te nazwy powinny być wewnętrznym szczegółem implementacji i nie polegać na! – Ben

+0

@Ben Nie otrzymasz od mnie żadnej opozycji ... – Destin

+1

Dlatego używasz 'niejawnie' ... próbując użyć' evidence $ 1' etc w twoim kodzie nie skompiluje się. –

Powiązane problemy