开发者

Scala ClassManifest instead of Type[T]

开发者 https://www.devze.com 2023-03-13 13:59 出处:网络
The following code def httpPost[T: ClassManifest](data: AnyRef): T = { val webResource = client.resource(\"http://localhost..\")

The following code

def httpPost[T: ClassManifest](data: AnyRef): T = {
  val webResource = client.resource("http://localhost..")
  val resp = webResource.post(classOf[ClientResponse], data)
  resp.getEntity(classManifest[T].erasure) //Need classOf[T] here 
}

results in this type mismatch compilation error

[INFO]  found   : _$1 whe开发者_StackOverflow社区re type _$1
[INFO]  required: T
[INFO]       resp.getEntity(classManifest[T].erasure)

Based on the answer to Scala classOf for type parameter it looks like it should work.

The erasure method returns java.lang.Class[_] and I presume that this is the problem so I have two questions:

  • Why does the class manifest return an existential type and not simply Class[T] - if it's the erasure of T, surely that will always be _ (underscore) because T is obviously unknown, which means its return value isn't as useful as I'd have expected.
  • What do I need to do to make the code work!

Update:

Thanks Kim and Jean-Phillipe for your answers.

I had previously tried a cast so the original last line was replaced with

val responseData = resp.getEntity(classManifest[T].erasure) //Runtime error
responseData.asInstanceOf[T]

and this compiles but there's now a runtime error because the getEntity method is passed the class of Object, which it can't process because it needs a more specific type (for which it has a handler). Although it's deferred until runtime, it again comes down to the erasure method not giving specific type information and that's why I thought that to solve the problem, the inline example must be solved.


There's something seriously wrong with this code. In particular:

def httpPost[T: ClassManifest](data: AnyRef): T = {
  val webResource = client.resource("http://localhost..")
  val resp = webResource.post(classOf[ClientResponse], data)
  resp.getEntity(classManifest[T].erasure) //Need classOf[T] here 
}

How is Scala supposed to know what the type of T is? Are you passing it explicitly when invoking httpPost? I suspect not, and that's the reason why erasure is returning Object for you.

As for why ClassManifest#erasure returns Class[_] instead of something else, I suspect the reason is that this is the type used by most Java methods, and since Class is invariant, if erasure returned Class[T], then you'd have to cast it to use it with those methods!


First question: No idea...

Second question: I think it is safe to cast here. You can use foo.asInstanceOf[Class[T]].


I believe that an existential type is returned to make it clear that the cast that you may want to make is your responsibility. Class is a bit weird: for instance, a Class[List[String]] should actually be typed as a Class[List[_]] as it does not carry any information about the String parametrization of List. The cast suggested by Kim is always safe when T is not itself a parametrized type.

0

精彩评论

暂无评论...
验证码 换一张
取 消