[英]How to specify linked types for asInstanceOf
The title is not too descriptive, but I'm not aware how the used pattern is properly called. 标题不太具描述性,但我不知道如何正确调用所使用的模式。 I hope all would become clear with example.
我希望所有人都能以身作则。
trait OneKnot[K <: Knot[K]] { this : K#One =>
type OK = K // for example only. To show that it is actually defined
def use(second : OK#Two)
}
trait TwoKnot[K <: Knot[K]] { this : K#Two => }
trait Knot[K <: Knot[K]] {
type One <: OneKnot[K]
type Two <: TwoKnot[K]
}
trait KnotExample extends Knot[KnotExample] {
override type One = OneExample
override type Two = TwoExample
}
trait OneExample extends OneKnot[KnotExample]
trait TwoExample extends TwoKnot[KnotExample]
object Test {
def testByName( one : OneExample, two : TwoExample ) = one.use(two)
def testByKnot[K <: Knot[K]]( one : K#One, two : K#Two ) = one.use(two)
def testByCast(knot : Knot[_], one : OneKnot[_], two : TwoKnot[_]) = one.asInstanceOf[knot.One].use(two.asInstanceOf[knot.Two])
def testByInnerCast(one : OneKnot[_], two : TwoKnot[_]) = one.use( two.asInstanceOf[one.OK#Two] )
}
Types OneExample
and TwoExample
is normally recognized by each other. 通常可以相互识别类型
OneExample
和TwoExample
。 The testByKnot
method shows it. testByKnot
方法显示它。 I can also call the use
method with static parametrization by Knot
. 我还可以通过
Knot
调用带有静态参数化的use
方法。 The types would be compatible, as shown in the testByKnot
method. 类型将兼容,如
testByKnot
方法所示。
But I need to discard type information to store data in a collection. 但是我需要丢弃类型信息以将数据存储在集合中。 eg
Map[Knot[_], OneKnot[_]]
. 例如
Map[Knot[_], OneKnot[_]]
。 So I need to restore types after extraction from collection using asInstanceOf
. 所以我需要使用
asInstanceOf
从集合中提取数据后还原类型。 But I failed to specify correctly to what types the cast needed. 但是我无法正确指定所需的转换类型。
In the last two test methods I get two corresponding errors: 在最后两种测试方法中,我得到两个相应的错误:
NotSameType.scala:25: error: type mismatch;
found : knot.Two
required: _$1#Two
def testByCast(knot : Knot[_], one : OneKnot[_], two : TwoKnot[_]) = one.asInstanceOf[knot.One].use(two.asInstanceOf[knot.Two])
^
NotSameType.scala:26: error: type Two is not a member of one.OK
def testByInnerCast(one : OneKnot[_], two : TwoKnot[_]) = one.use( two.asInstanceOf[one.OK#Two] )
How the cast should be done properly? 如何正确地进行投射?
How about using type K <: Knot[K]
to glue/cast the two knots types together? 如何使用类型
K <: Knot[K]
将两种类型的结粘合/浇铸在一起?
object Test {
def testByName(one: OneExample, two: TwoExample) = one.use(two)
def testByKnot[K <: Knot[K]](one: K#One, two: K#Two) = one.use(two)
def testByCast[K <: Knot[K]](one: OneKnot[_], two: TwoKnot[_]) =
one.asInstanceOf[K#One].use(two.asInstanceOf[K#Two])
def testByInnerCast[K <: Knot[K]](one: OneKnot[_], two: TwoKnot[_]) =
one.asInstanceOf[K#One].use(two.asInstanceOf[K#One#OK#Two])
}
You can then call one of the cast methods directly. 然后,您可以直接调用其中一种强制转换方法。
val one = new OneExample { def use(second: TwoExample) = ??? }
val two = new TwoExample {}
val result = testByCast(one, two)
The answer summarize approach suggested by Andy 答案总结了安迪建议的方法
You may use type parametrization but never specify the needed tag. 您可以使用类型参数化,但不要指定所需的标签。 see the sample:
查看示例:
def testByDiscard[K <: Knot[K]]( one : OneKnot[_], two : TwoKnot[_] ) =
one.asInstanceOf[K#One].use(two.asInstanceOf[K#Two])
The mystery is that compiler managed to substitute something meaningful to the type parameters. 神秘之处在于,编译器设法将有意义的内容替换为类型参数。 The type parameter may never be specified, but this construction would still works.
类型参数可能永远不会被指定,但是这种构造仍然有效。 Anyway java gets rid of all type parameters, so no crucial information is lost.
无论如何,java摆脱了所有类型参数,因此不会丢失任何关键信息。
I was curious what is the magic type the compiler use. 我很好奇编译器使用什么魔术类型。 And add implicit type tag to get it.
并添加隐式类型标记以获取它。 It was just simple
Nothing
not a complicated type erasure type. 只是简单
Nothing
不是复杂的类型擦除类型。 Static type checker really does not complain agains the further usage: 静态类型检查器确实不再抱怨进一步的用法:
val exo : OneExample = new OneExample
val ext : TwoExample = new TwoExample
Test.testByDiscard[Nothing](exo, ext)
But fails as expected when trying to cast directly to Nothing#One
or Nothing#Two
. 但是尝试直接转换为
Nothing#One
或Nothing#Two
时,按预期方式失败。 It also fails when trying with calling testByKnot[Nothing]
that is identical to discard case but without asInstanceOf
call. 当尝试调用与废弃情况相同但没有
asInstanceOf
调用的testByKnot[Nothing]
,它也会失败。 It is quite amusing how the scala type manager works, but it deserves separate question. scala类型管理器的工作方式非常有趣,但是值得单独提出一个问题。
This question is closed with answer provided by Andy and detailed by me above. 这个问题已经由安迪(Andy)提供并在上面由我详细介绍了。 It just works.
它只是工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.