假设我有
val flag = true
Run Code Online (Sandbox Code Playgroud)
为什么会导致类型Product with Serializable with Animal而不只是类型Animal?
class Animal(name : String)
case class Herbivore(name : String) extends Animal(name)
case class Carnivore(name : String) extends Animal(name)
val cow = new Herbivore("cow")
val tiger = new Carnivore("tiger")
if (flag) cow else tiger // Why is type Product with Serializable with Animal?
Run Code Online (Sandbox Code Playgroud)
案例类自动扩展, Product with Serializable因此
class Animal(name : String)
case class Herbivore(name : String) extends Animal(name)
case class Carnivore(name : String) extends Animal(name)
Run Code Online (Sandbox Code Playgroud)
实际上是
class Animal(name : String)
case class Herbivore(name : String) extends Animal(name) with Product with Serializable
case class Carnivore(name : String) extends Animal(name) with Product with Serializable
Run Code Online (Sandbox Code Playgroud)
因此,if (flag) cow else tiger编译器可以推断出的最精确的表达式类型是Product with Serializable with Animal。如果我们从案例类更改为像这样的类
class Animal(name : String)
class Herbivore(name : String) extends Animal(name)
class Carnivore(name : String) extends Animal(name)
Run Code Online (Sandbox Code Playgroud)
那么if-else表达式的推断类型确实是Animal。
按照@TravisBrown的建议,使ADT根目录Product with Serializable像这样扩展
abstract class Animal(name : String) extends Product with Serializable
case class Herbivore(name : String) extends Animal(name)
case class Carnivore(name : String) extends Animal(name)
Run Code Online (Sandbox Code Playgroud)
也会使if-else表达式的推断类型也变为Animal。