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]?
Odpowiedz
Istnieją trzy predefiniowane metody Predef
że zrobi to za Manifest
s, ClassManifest
OptManifest
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
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. –
@RM Dobra sztuczka. Sądzę, że musiałby to być 'UsefulTypeclass [T]()' (z dodatkowym '()'). –
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) –
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?
Zawsze można zadeklarować metodę o mniejszej nazwie, ale nie należy _nie polegać na magicznych nazwach generowanych przez Scalac. –