case class 从 trait 继承异常行为
case class inheritance from trait behaving unexpectedly
我有一个 Person
的特征,以及一个继承自这个特征的案例 class,我希望如果我有一个函数,除了从 Person
到 Future[Person]
并且我会将它从 Male
传递给 Future[Male]
,这将通过。像这样:
trait Person {
val name: String
val age: Int
}
case class Male (override val name: String, override val age: Int, height: Double) extends Person
val male1 = Male(name = "John", age = 30, height = 1.80)
def something(person: Person => Future[Person]): Unit = {
println(s"person is $person")
}
def maleToFutureMale (male: Male) = Future.successful(male)
something(maleToFutureMale)
但出现编译错误:
这与 case 类 或 traits 无关,它与函数子类型有关。
Scala 拒绝此类代码,因为 Male
是 Person
,Male => Future[Male]
不是 Person => Future[Person]
。
要理解原因,请考虑以下类型
case class Female(val name, val age) extends Person
以及您的 something
方法的以下增量
def something(personToFuture: Person => Future[Person]): Unit = {
val future = personToFuture(Female("Lisa", 53))
}
以上代码完全正确。我们可以将 Female
传递给 personToFuture
因为 Female
是 Person
.
如果语言允许我们将 maleToFutureMale
传递给 something
,那么它将允许我们将 Female
传递给需要 Male
的函数。
所有这些并不是说函数类型是不变的,您传递给 something
的参数必须具有类型 Person => Future[Person]
。函数类型确实有子类型关系。
函数类型在它们的 return 类型中是 contravariant in their parameter types and covariant。
一般来说,给定一个函数类型,F
,一个具有 less 特定参数类型和 more 的函数类型特定 return 类型是 F
.
的子类型
例如,以下是完全有效的
val anyToFutureOfMale: Any => Future[Male] = _ => Future.successful(Male("Robert", 39, 1.8))
something(anyToFutureOfMale)
以上是有效的,因为 Any => Male
是 Person => Person
。由于 Person
是 Any
,因此将 Person
传递给期望 Any
的函数是完全合理的,同样,由于 Male
是 Person
从函数 return 接收 Person
.
的 Male
听起来很完美
那是因为您将子类型与 co/contravariance 混用了。
男性是一个人,一个男性=>未来[男性]不是一个人=>未来[人]。
我有一个 Person
的特征,以及一个继承自这个特征的案例 class,我希望如果我有一个函数,除了从 Person
到 Future[Person]
并且我会将它从 Male
传递给 Future[Male]
,这将通过。像这样:
trait Person {
val name: String
val age: Int
}
case class Male (override val name: String, override val age: Int, height: Double) extends Person
val male1 = Male(name = "John", age = 30, height = 1.80)
def something(person: Person => Future[Person]): Unit = {
println(s"person is $person")
}
def maleToFutureMale (male: Male) = Future.successful(male)
something(maleToFutureMale)
但出现编译错误:
这与 case 类 或 traits 无关,它与函数子类型有关。
Scala 拒绝此类代码,因为 Male
是 Person
,Male => Future[Male]
不是 Person => Future[Person]
。
要理解原因,请考虑以下类型
case class Female(val name, val age) extends Person
以及您的 something
方法的以下增量
def something(personToFuture: Person => Future[Person]): Unit = {
val future = personToFuture(Female("Lisa", 53))
}
以上代码完全正确。我们可以将 Female
传递给 personToFuture
因为 Female
是 Person
.
如果语言允许我们将 maleToFutureMale
传递给 something
,那么它将允许我们将 Female
传递给需要 Male
的函数。
所有这些并不是说函数类型是不变的,您传递给 something
的参数必须具有类型 Person => Future[Person]
。函数类型确实有子类型关系。
函数类型在它们的 return 类型中是 contravariant in their parameter types and covariant。
一般来说,给定一个函数类型,F
,一个具有 less 特定参数类型和 more 的函数类型特定 return 类型是 F
.
例如,以下是完全有效的
val anyToFutureOfMale: Any => Future[Male] = _ => Future.successful(Male("Robert", 39, 1.8))
something(anyToFutureOfMale)
以上是有效的,因为 Any => Male
是 Person => Person
。由于 Person
是 Any
,因此将 Person
传递给期望 Any
的函数是完全合理的,同样,由于 Male
是 Person
从函数 return 接收 Person
.
Male
听起来很完美
那是因为您将子类型与 co/contravariance 混用了。 男性是一个人,一个男性=>未来[男性]不是一个人=>未来[人]。