например, мне нужно получить доступ к манифесту в функции def a[A:ClassManifest]
, чтобы получить класс стирания. Я могу использовать функцию Predef.implicitly, но в этом случае мой код будет таким, как если бы я использовал полную форму def a[A](implicit b:ClassManifest[A])
. Так есть ли сгенерированные имена для этих неявных аргументов?Как я могу получить доступ к неявному «неявному», т. Е. Def a [A: B] или def a [A <% B]?
ответ
Есть три предопределенные методы Predef
, которые будут делать это за Manifest
с, ClassManifest
s и s OptManifest
: manifest[T]
, classManifest[T]
и optManifest[T]
соответственно. Вы можете написать свои собственные «неявные геттеры» для других классов типов в соответствии с одним и тем же шаблоном. Вот, например manifest[T]
:
def manifest[T](implicit m: Manifest[T]) = m
Так вот, как вы могли бы написать свой собственный:
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
Как аккуратный трюк: если вы назовете неявный геттер «применить» и поместите его на сопутствующий объект «Полезный», вы можете использовать «ПолезныйТипец [Т]» в качестве значения, представляющего экземпляр класса типов для Т, не импортируя ничего больше, чем сам класс. –
@RM Отличный трюк. Я предполагаю, что это должно быть «ПолезноТипец [T]()» (с дополнительным «()»). –
На самом деле он не нуждается в parens. Если у вас есть (простить отсутствие форматирования) объект TC {def apply [T] (неявный x: TC [T]) = x}, вы можете буквально вызывать его только с помощью «TC [SomeClass]», потому что «apply» определяется как беспараметрированный метод с неявным списком параметров, а [SomeClass] однозначно устраняет его только из ссылки на объект TC. Это desugars для TC.apply [SomeClass] (theImplicitValue) –
scalap на помощь!
Я взял этот код:
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") }
}
и побежал через scalap. Вот что я получил:
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 */ }
}
Как вы можете видеть, первый неявный манифеста называется evidence$1
. Второй и третий - , хотя в другом объеме! - можно назвать evidence$2
и evidence$3
. Итак ... так вы ссылаетесь на Manifests.
Несмотря на это, мне кажется немного страшным, что удаление манифеста, которое выше в классе, изменит имя манифеста, расположенного ниже в файле. Точно так же это не помогает, что подсветка синтаксиса плагина IntelliJ Scala кажется, что переменные Manifest в области в four()
: evidence$1
и evidence$2
, и не считает, что evidence$3
является допустимой переменной (хотя это, и evidence$1
нет). В целом, может быть, эти вещи следует учитывать как предупреждающие знаки о игре с неявными переменными манифеста?
Вы всегда можете объявить метод с меньшим именем, но вы не должны зависеть от магических имен, созданных Scalac. –