类的实例与其伴随对象之间的关系

时间:2016-08-14 14:09:19

标签: scala object

我有以下类和伴侣对象:

class TestMatch(val i: Int)

object TestMatch{
  def apply(i: Int) = new TestMatch(i)
  def unapply(tm : TestMatch): Option[Int] = Some(tm.i)
}

现在考虑以下简单程序:

println("isAssignableFrom: " + classOf[TestMatch].isAssignableFrom((tm.getClass)))
println("equality: " + classOf[TestMatch].equals((tm.getClass)))
println("instanceOf:" + TestMatch.isInstanceOf[TestMatch])

打印:

isAssignableFrom: true
equality: true
instanceOf:false

怎么可能?还没有在Java中遇到过这个。

1 个答案:

答案 0 :(得分:3)

在每个示例中,您没有提到相同的TestMatch概念。

  • classOf[TestMatch]instanceOf[TestMatch]TestMatch称为类型。单身人士没有定义类型。
  • TestMatch.something()是对单例对象TestMatch
  • 上的方法的调用

现在可能有点令人困惑的是:

object Singleton
println(Singleton.isInstanceOf[Singleton]) // prints true

我猜测当单例是伴侣对象时,Scala会优先考虑该类。

修改

正如阿列克谢·罗曼诺夫指出的那样,scala.Singleton实际上是在Scala SDK中定义的,每个单例对象都会扩展...让我们用另一个名字重新开始:

object MySingleton
println(MySingleton.isInstanceOf[MySingleton])

这不编译,因为单例不定义类型。有一种方法可以编译。

println(MySingleton.isInstanceOf[MySingleton.type]) // true

这就是你如何证明你不是指同一件事。最后的例子,让我们试试

class MyClassWithCompanion
object MyClassWithCompanion

val x = new MyClassWithCompanion

println(MyClassWithCompanion.isInstanceOf[MyClassWithCompanion])      // false
println(MyClassWithCompanion.isInstanceOf[MyClassWithCompanion.type]) // true
println(MyClassWithCompanion.isInstanceOf[x.type]                     // false

这很微妙,但这就是它的含义:

  • .type是应用于实例并返回其类型
  • 的运算符
  • x.type只能在x是某个实例的情况下定义,因此除非此类具有伴随对象,否则MyClass.type将无法编译。因此,MyClassWithCompanion.type必然是指伴侣对象(它是一个实例)而不是类本身
  • 伴侣的类型和类本身的类型是不同的。你无法用单身X替换X的实例,这是有道理的,因为它们具有不同的性质。