【发布时间】:2021-06-27 21:58:06
【问题描述】:
结构如下:
trait ParentType
trait ChildType extends ParentType
case class FooBar[+T <: ParentType](s: String, data: T)
object FooBar {
def apply[T <: ChildType](i: Int, data: T): FooBar[T] = new FooBar(s"$i", data)
}
case class Foo(a: Int) extends ParentType
case class Bar(s: String) extends ChildType
def function1[T <: ParentType](obj: FooBar[T]): Unit = ()
def function2[T <: ChildType](obj: FooBar[T]): Unit = ()
是否可以(以及以何种方式)更改function1 和function2 的签名(带有泛型声明),使得function1 只能排除FooBar 类型为T 的参数,即直接后代的ParentType(并禁止任何T 的直接后代ChildType)和function2 以另一种方式 - 除了只有T 的参数是ChildType 的直接后代并禁止所有ParentType T的
换句话说,这不应该编译
function1(FooBar("a", Bar("1"))) //because Bar is not direct descendant of ParentType
【问题讨论】:
-
你为什么要这么复杂和奇怪的限制类型?您的要求甚至直接违反了 Liskov 原则,这让我认为这是一个 XY 问题,并且您使用继承的正确解决方案是一个失败的抽象。 - 如果你能解释你的元问题,我们可能会提供更好的选择。
-
假设 ParentType 是
Animal而 ChildType 是Mammal。我希望function2只接受哺乳动物的“容器”FooBar,而function1- 所有其他组类型的动物(但不是哺乳动物):Fish、Reptile等。希望现在更清楚了。谢谢。 -
你可以为
def function1[T](data: FooBar[T])(implicit ev: T <:< ChildType)做function2你可能宁愿重载function1这样如果没有找到证据,就会选择重载(不确定这是否可行) i> 或从 Shapeless 中拉出=!:=。 -
@LuisMiguelMejíaSuárez 谢谢,使用 shapless 解决了我的问题