Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/12.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
使用scala泛型和清单在类内强制转换_Scala_Type Erasure_Erasure - Fatal编程技术网

使用scala泛型和清单在类内强制转换

使用scala泛型和清单在类内强制转换,scala,type-erasure,erasure,Scala,Type Erasure,Erasure,我有两个班,Holder(目前没有更好的名字)和Holder。 支架必须通过支架连接,支架具有任何类型的支架阵列。 因此,它必须采取任何类型。我想让setValue进行类型检查,以确保任何输入都确实是T类型。 我读过一些关于使用清单的书,但是我有点迷路了。有什么办法可以满足我的要求吗 class Holders { var values = Array[Any]() var _holders = Array[Holder[_]]() def setData(index:

我有两个班,Holder(目前没有更好的名字)和Holder。 支架必须通过支架连接,支架具有任何类型的支架阵列。 因此,它必须采取任何类型。我想让setValue进行类型检查,以确保任何输入都确实是T类型。 我读过一些关于使用清单的书,但是我有点迷路了。有什么办法可以满足我的要求吗

class Holders {
    var values = Array[Any]()
    var _holders = Array[Holder[_]]()

    def setData(index: Int, newValue: Any) {
        values(index) = newValue
        _holders(index).setValue(newValue)
    }
}

class Holder[T](someData: String, initValue: T) {
    private var value : T = initValue
    def getValue : T = value
    def setValue(newValue: Any)(implicit m: Manifest[T]) = {
      if (newValue.isInstanceOf[T])
        value = newValue.asInstanceOf[T]
    }
}
你可以

注意:
Manifest
已被弃用并替换为
TypeTag
ClassTag
,但这并不影响本答案的其余部分

通常,当需要清单/类型标记时,您确切地知道在编译时发生了什么,但也希望将这些信息保存到运行时。在这种情况下,您还必须处理这样一个事实,即即使在编译时,
\u持有者(索引)
也不能告诉您它返回的是什么类型的
持有者

根据
\u支架
的构建方式,可能会将其替换为不成形库中的,这将完全满足您的需要

否则,您的想法是正确的,在运行时测试类型。诀窍是使用
TypeTag
捕获持有者的基本类型和新值的类型

请注意,必须在所有嵌套方法上指定
TypeTag
上下文绑定,以便可以在隐式范围内向下传递调用堆栈。
TypeTag
的存在允许
typeOf
工作

import scala.reflect.runtime.universe._ //for TypeTag

class Holders {
  var values = Array[Any]()
  var _holders = Array[Holder[_]]()

  def setData[V: TypeTag](index: Int, newValue: V): Unit = {
    values(index) = newValue
    _holders(index).setValue(newValue)
  }
}

class Holder[T: TypeTag](someData: String, initValue: T) {
  private var value: T = initValue
  def getValue: T = value

  def setValue[V: TypeTag](newValue: V): Unit =
    if(typeOf[V] <:< typeOf[T]) {
      value = newValue.asInstanceOf[T]
}
不过,我强烈建议您支持
TypeTag

你可以

注意:
Manifest
已被弃用并替换为
TypeTag
ClassTag
,但这并不影响本答案的其余部分

通常,当需要清单/类型标记时,您确切地知道在编译时发生了什么,但也希望将这些信息保存到运行时。在这种情况下,您还必须处理这样一个事实,即即使在编译时,
\u持有者(索引)
也不能告诉您它返回的是什么类型的
持有者

根据
\u支架
的构建方式,可能会将其替换为不成形库中的,这将完全满足您的需要

否则,您的想法是正确的,在运行时测试类型。诀窍是使用
TypeTag
捕获持有者的基本类型和新值的类型

请注意,必须在所有嵌套方法上指定
TypeTag
上下文绑定,以便可以在隐式范围内向下传递调用堆栈。
TypeTag
的存在允许
typeOf
工作

import scala.reflect.runtime.universe._ //for TypeTag

class Holders {
  var values = Array[Any]()
  var _holders = Array[Holder[_]]()

  def setData[V: TypeTag](index: Int, newValue: V): Unit = {
    values(index) = newValue
    _holders(index).setValue(newValue)
  }
}

class Holder[T: TypeTag](someData: String, initValue: T) {
  private var value: T = initValue
  def getValue: T = value

  def setValue[V: TypeTag](newValue: V): Unit =
    if(typeOf[V] <:< typeOf[T]) {
      value = newValue.asInstanceOf[T]
}

不过,我强烈建议您支持
TypeTag

类型擦除使这种事情。。。很难。简而言之,编译代码后,所有类型参数都将替换为
Any
。为了理解其含义,请考虑下面的例子:

trait Foo[T] { def isT(a: Any): Boolean = a.isInstanceOf[T] }

object Bar extends Foo[String]

Bar.isT("foo") // true
Bar.isT(42)    // also true, as Int <: Any

现在你看到这一点并说“这不意味着赋值实际上是
value=v.asInstanceOf[Any]
?”,答案是肯定的-
value
也被擦除为
Any
。铸造没有任何作用,从某种意义上说,
v.asInstanceOf[T]
并不意味着“将
v
转换为
T
”。相反,你所做的是说“哦,是的,
v
完全是一个
T
-诚实!”,因为编译器很幼稚,它相信你。

类型擦除使这种事情。。。很难。简而言之,编译代码后,所有类型参数都将替换为
Any
。为了理解其含义,请考虑下面的例子:

trait Foo[T] { def isT(a: Any): Boolean = a.isInstanceOf[T] }

object Bar extends Foo[String]

Bar.isT("foo") // true
Bar.isT(42)    // also true, as Int <: Any


现在你看到这一点并说“这不意味着赋值实际上是
value=v.asInstanceOf[Any]
?”,答案是肯定的-
value
也被擦除为
Any
。铸造没有任何作用,从某种意义上说,
v.asInstanceOf[T]
并不意味着“将
v
转换为
T
”。相反,您所做的是说“哦,是的,
v
完全是一个
T
-诚实!”,因为编译器很幼稚,它相信您。

在您的示例中,在setValue中测试T不是因为类型擦除而没有做任何事情吗?当我尝试你所拥有的东西时,我得到一个警告,由于擦除,这将不起作用,因为对于任何可能的
nv
,都是真的。那么有什么方法可以让我检查我的any是否属于类型T?为什么清单不支持=:=:(正在比较清单[T]。runtimeClass==清单[V].runtimeClass等价物?您不需要这里的
=:=
。我假设您希望能够将
FordFiesta
放入
支架[汽车]
在您的示例中,在setValue中测试t不是因为类型擦除而没有做任何事情吗?我在尝试您拥有的东西时收到一条警告,由于擦除,这将不起作用,因为
案例nv:t
对于任何可能的
nv
都是正确的。那么我有没有办法检查我的any是否属于类型t?为什么不显示支持=:=:(正在比较清单[T]。runtimeClass==清单[V]。runtimeClass等效物?您不希望
=:=
在这里。我假设您希望能够将
FordFiesta
放入
支架[Car]
是否会使用=:=修复我的超类问题?是否有任何方法可以使用清单做完全相同的事情?理想情况下,我会坚持使用scala2.8我相信您应该能够使用清单代替标记来完成同样的事情,因为
TypeTag
是与反射API集成的清单的演变-请参阅API文档n:“超类型问题”源于调用者可以通过“欠报告”参数类型来“撒谎”,例如
setValue[Any](“foo”)
。同样值得注意的是,您得到的是d