加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Scala中的抽象类型/类型参数

发布时间:2020-12-16 09:33:15 所属栏目:安全 来源:网络整理
导读:我正在尝试写一些Scala代码,需要执行以下操作: class Test[Type] { def main { SomeFunc classOf[Type] val testVal: Type = new Type() } } 它是失败的。我显然不了解Scala通用参数。很明显地,误解是在C中,模板基本上像字符串替换一样,所以新的Type()
我正在尝试写一些Scala代码,需要执行以下操作:

class Test[Type] { 
   def main {
       SomeFunc classOf[Type]
       val testVal: Type = new Type()
    }
 }

它是失败的。我显然不了解Scala通用参数。很明显地,误解是在C中,模板基本上像字符串替换一样,所以新的Type()只要传入的类具有默认构造函数就可以工作。但是,在Scala中,类型是不同类型的对象。

解决方法

你指出,C有模板。总之,C说“有一个测试所有类型T,以便测试编译”。这样就可以轻松地在T上隐式添加约束,但是它们是隐含的,并且对于类的用户而言,可能难以理解,而无需阅读代码。

Scala的参数多态性(又名泛型)的工作更像ML,Haskell,Java和C#。在Scala中,当你写“class Test [T]”时,你说“所有T都存在一个类型Test [T]”,没有约束。这对于正式的理解来说更为简单,但它的确意味着你必须明确约束。例如,在Scala中,您可以说“Class Test [T<:Foo]”来表示T必须是Foo的子类型。 C#有一种方法来向T添加一个关于构造函数的约束,但不幸的是Scala没有。 在Scala中有几种方法可以解决您的问题。一个是类型安全的,但是一个bt更冗长。另一个不是类型安全。 类似安全的方式看起来像

class Test[T](implicit val factory : () => T) {
  val testVal = factory
}

那么你可以有一个工厂的一个类型在您的系统中有用的类型

object Factories {
  implicit def listfact[X]() = List[X]()
  implicit def setfact[X]() = Set[X]()
  // etc
}

import Factories._
val t = new Test[Set[String]]

如果您的图书馆的用户需要自己的工厂,那么他们可以添加自己等同的工厂对象。这个解决方案的一个优点是可以使用任何一个工厂,无论是否有一个无参数构造函数。

不那么安全的方式使用Scala中的反射和特征,称为清单,这是一种解决Java约束关于类型擦除的方法

class Test[T](implicit m : Manifest[T]) {
   val testVal = m.erasure.newInstance().asInstanceOf[T]
 }

有了这个版本,你仍然写

class Foo
val t = new Test[Foo]

但是,如果没有no-arg构造函数可用,则会得到运行时异常而不是静态类型错误

scala> new Test[Set[String]] 
java.lang.InstantiationException: scala.collection.immutable.Set
at java.lang.Class.newInstance0(Class.java:340)

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读