scala – 可以对类型符合结果的泛型值执行模式匹配吗?
发布时间:2020-12-16 19:24:28 所属栏目:安全 来源:网络整理
导读:是否可以执行模式匹配,其结果符合外部方法的类型参数?例如.给定: trait Key[A] { def id: Int def unapply(k: Key[_]): Boolean = k.id == id // used for Fail2 def apply(thunk: = A): A = thunk // used for Fail3}trait Ev[A] { def pull[A1 : A](key:
是否可以执行模式匹配,其结果符合外部方法的类型参数?例如.给定:
trait Key[A] { def id: Int def unapply(k: Key[_]): Boolean = k.id == id // used for Fail2 def apply(thunk: => A): A = thunk // used for Fail3 } trait Ev[A] { def pull[A1 <: A](key: Key[A1]): Option[A1] } trait Test extends Ev[AnyRef] { val key1 = new Key[String] { def id = 1 } val key2 = new Key[Symbol] { def id = 2 } } 是否有一个Test(它的pull方法)的实现,它在key参数上使用模式匹配,并为每个检查的键返回Option [A1],而不使用asInstanceOf? 一些可悲的尝试: class Fails1 extends Test { def pull[A1 <: AnyRef](key: Key[A1]): Option[A1] = key match { case `key1` => Some("hallo") case `key2` => Some('welt) } } class Fails2 extends Test { def pull[A1 <: AnyRef](key: Key[A1]): Option[A1] = key match { case key1() => Some("hallo") case key2() => Some('welt) } } class Fails3 extends Test { def pull[A1 <: AnyRef](key: Key[A1]): Option[A1] = key match { case k @ key1() => Some(k("hallo")) case k @ key2() => Some(k('welt)) } } 没有用,显然……唯一的解决方案就是施放: class Ugly extends Test { def pull[A1 <: AnyRef](key: Key[A1]): Option[A1] = key match { case `key1` => Some("hallo".asInstanceOf[A1]) case `key2` => Some('welt .asInstanceOf[A1]) } } val u = new Ugly u.pull(u.key1) u.pull(u.key2) 解决方法
问题确实是模式匹配忽略了所有已擦除的类型.然而,人们可以使用一些隐含的诡计.以下内容将保留返回类型匹配所提供的类型解析.
abstract class UnErased[A] implicit case object UnErasedString extends UnErased[String] implicit case object UnErasedSymbol extends UnErased[Symbol] class UnErasedTest extends Test { def pull[ A1 <: AnyRef ]( key: Key[ A1 ])(implicit unErased: UnErased[A1]): Option[ A1 ] = unErased match { case UnErasedString if key1.id == key.id => Some( "hallo" ) case UnErasedSymbol if key2.id == key.id => Some( 'welt ) case _ => None } } val u = new UnErasedTest println( u.pull( u.key1 ) ) println( u.pull( u.key2 ) ) 然而,这几乎等同于仅定义Key的单独子类.我发现以下方法更可取但是如果现有代码使用Key [String]而无法更改为必要的KeyString(或者需要更改太多工作),它可能无效. trait KeyString extends Key[String] trait KeySymbol extends Key[Symbol] trait Test extends Ev[ AnyRef ] { val key1 = new KeyString { def id = 1 } val key2 = new KeySymbol { def id = 2 } } class SubTest extends Test { def pull[ A1 <: AnyRef ]( key: Key[ A1 ]): Option[ A1 ] = key match { case k: KeyString if key1.id == k.id => Some( "hallo" ) case k: KeySymbol if key2.id == k.id => Some( 'welt ) case _ => None } } val s = new SubTest println( s.pull( s.key1 ) ) println( s.pull( s.key2 ) ) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |