Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Generics scala的通用对象加载函数_Generics_Scala_Manifest_Scala 2.8_Parameterization - Fatal编程技术网

Generics scala的通用对象加载函数

Generics scala的通用对象加载函数,generics,scala,manifest,scala-2.8,parameterization,Generics,Scala,Manifest,Scala 2.8,Parameterization,我从一个在后端使用Hibernate(JPA)的Scala应用程序开始。为了加载对象,我使用以下代码行: val addr = s.load(classOf[Address], addr_id).asInstanceOf[Address]; 不用说,这有点痛苦。我编写了一个助手类,如下所示: import org.hibernate.Session class DataLoader(s: Session) { def loadAddress(id: Long): Address = {

我从一个在后端使用Hibernate(JPA)的Scala应用程序开始。为了加载对象,我使用以下代码行:

val addr = s.load(classOf[Address], addr_id).asInstanceOf[Address];
不用说,这有点痛苦。我编写了一个助手类,如下所示:

import org.hibernate.Session

class DataLoader(s: Session) {
  def loadAddress(id: Long): Address = {
    return s.load(classOf[Address], id).asInstanceOf[Address];
  }
  ...
}
import org.hibernate.Session
class DataLoader(s: Session) {
  def load[A](id: Long)(implicit m: Manifest[A]): A = {
    return m.erasure.asInstanceOf[Class[A]].cast(s.load(m.erasure, id));
  }
}
import org.hibernate.Session
class DataLoader(s: Session) {
  def load[A : Manifest](id: Long): A = {
    return s.load(manifest[A].erasure, id).asInstanceOf[A];
  }
}
所以,现在我可以做到:

val dl = new DataLoader(s)
val addr = dl loadAddress(addr_id)
问题是:我如何编写一个通用的参数化方法,它可以使用相同的模式加载任何对象?i、 e

val addr = dl load[Address](addr_id)
(或者类似的东西。)


我是Scala的新手,所以请原谅这里有什么特别可怕的地方。

一种方法是利用
java.lang.Class.cast
方法来执行以下操作:

def load[A](clazz: Class[A], id: Long)(implicit s: Session) : A 
       = clazz.cast(s.load(clazz, id))
那么用法如下:

implicit val s = ...//get hibernate session
val addr = load(classOf[Address], 1)
它与您已经拥有的没有太大区别,但是为了访问
实例,您需要传入它

我很有信心您不能安全地使用
清单
做您想做的事情,因为它们不能在编译时提供您需要的参数化
类[地址]
,以便强制转换工作(它们只能提供
类[\u]
的擦除)。我没有看到任何其他机制可以从
Manifest

当然,您可以使用
asInstanceOf[A]
而不是
cast
,但这会在编译时被擦除,以
isInstanceOf[Object]
,因此在编译时类型检查方面是无用的(因此是不可取的)。

这里是:

import org.hibernate.Session
class DataLoader(s: Session) {
  def load[A](id: Long)(implicit m: Manifest[A]): A = {
    return s.load(m.erasure, id).asInstanceOf[A];
  }
}
编辑——或者,为了确保由于hibernate返回错误对象而导致的任何强制转换错误都会在
加载
中发生,如下所示:

import org.hibernate.Session

class DataLoader(s: Session) {
  def loadAddress(id: Long): Address = {
    return s.load(classOf[Address], id).asInstanceOf[Address];
  }
  ...
}
import org.hibernate.Session
class DataLoader(s: Session) {
  def load[A](id: Long)(implicit m: Manifest[A]): A = {
    return m.erasure.asInstanceOf[Class[A]].cast(s.load(m.erasure, id));
  }
}
import org.hibernate.Session
class DataLoader(s: Session) {
  def load[A : Manifest](id: Long): A = {
    return s.load(manifest[A].erasure, id).asInstanceOf[A];
  }
}
在Scala 2.8上,您也可以这样编写:

import org.hibernate.Session

class DataLoader(s: Session) {
  def loadAddress(id: Long): Address = {
    return s.load(classOf[Address], id).asInstanceOf[Address];
  }
  ...
}
import org.hibernate.Session
class DataLoader(s: Session) {
  def load[A](id: Long)(implicit m: Manifest[A]): A = {
    return m.erasure.asInstanceOf[Class[A]].cast(s.load(m.erasure, id));
  }
}
import org.hibernate.Session
class DataLoader(s: Session) {
  def load[A : Manifest](id: Long): A = {
    return s.load(manifest[A].erasure, id).asInstanceOf[A];
  }
}
您还可以将其与隐式会话组合,建议如下:


请注意,不能将上下文视图表示法(
A:Manifest
)与其他隐式参数组合使用。

有趣。这会让事情变得更整洁。。。但是你也教了我一些新的Scala结构。谢谢你。顺便说一下<代码>安装[A]
是否被擦除?那没有任何意义。此外,擦除发生在运行时,而不是编译时。另一方面,我从未想过使用
Class[a]
a
进行强制转换。有趣。我同意Daniel的观点,没有理由让Manifest不能在这里工作。@Daniel-擦除发生在编译时。您可以编写强制转换为参数化类型(如a)的代码,但该类型在编译时会被删除到其上限,在本例中为Object。因此,在运行时实际发生的转换是对对象的(无意义的)转换。我将遵从您关于scala的智慧,但不是java:-)@oxbow我不确定我们是否同意这里的编译时的含义。
load
返回的类型,虽然在运行时是一个
对象
,但在编译时肯定会进行语法检查。@Daniel-您的asInstanceOf cast恐怕不是很安全。考虑两个语句<代码> ValA= Load [地址](1)< /代码>和<代码> Valb:任何= Load [地址](2)< /代码>。在第二种情况下,实际上没有对
Address
类进行强制转换(它们被删除),并且您相信Hibernate会实际返回正确类型的实例(公平地说,它肯定会返回)。@oxbow我明白了。您的观点是,
类.cast
将在
加载
中导致运行时错误,而不是留下一些以后可能会导致问题的内容?是的-正是这样。这里唯一的“正确”转换发生在
load
方法之外,并由编译器插入,因为引用
a
的类型是Address。如果调用
load
方法并将其分配给
Any
,则不会发生CCE,并且您可能会发现有故障line@oxbow那好吧。我添加了一个更安全的版本,根据我做的一些测试,它应该可以工作。
作为
的替代品的位置尤其令人惊讶。