Is Object an instance of a class or is it a singleton class?

If Object is an instance of a class it is first class, i.e. can be passed as value but it cannot extends classes and interface as this would require Object to be a subtype of a type{Class,Trait} which needs to be type as well. Further, an instance of a class is not necessarily an singleton object, it can also be a single point (unit).

If Object is a singleton class it can extends other classes/interfaces as well but it can’t be passed to other functions as it is a class, too.

Now, which definition fits that of Object?

Or is every value seen as a singleton of its own, i.e. it is also a type?
Does the meaning of extends depends on Object vs Class, e.g. extends(A,B) does not require A<:B?

I believe this should be on the users discourse.

But anyways, if you are referring to the object keyword. What it does under the hood (at bytecode level) is to create a class an a single instance of that class.
However at language level, you should think of it as a value, which has its own type, but can be a subtype of other types.

This question is posted in the wrong place - it’s for users, not contributors. I’ll answer anyway.

java.lang.Object is better known as AnyRef in Scala.

It is a non-final non-abstract class with a whole bunch of methods related to thread synchronisation.

… because that’s just how Java rolls, why wouldn’t you need to be able to synchronise mutable access to every single object reference in your system?

AnyRef (a.k.a Object) is a class, it has no companion object / static members, it can be both subclassed and directly instantiated (which is of no value, unless you’re using the resulting naked object for thread synchronisation).

In Java, it extends nothing. In Scala it extends the root type (not class, not interface) Any.

@BalmungSan wrote:

However at language level, you should think of it as a value, which has its own type, but can be a subtype of other types.

Did you mean the type of object can be a subtype of something or the object itself, the latter doesn’t make sense unless there is no distinction between any of these types.

@kevinwright wrote:

This question is posted in the wrong place - it’s for users, not contributors. I’ll answer anyway.

Sorry, I missed that.
I missed, too that there is an Object class, like in Java. I thought there was only Any, AnyRef,…
I meant the object named by the object keyword. It doesn’t make sense for me that it is subtypeable and a value at the same time, maybe I just misunderstand it.

Every named value has its specific type that can be referred to:

object SomeObject
val SomeValue = 5

val x: SomeObject.type = SomeObject
val y: SomeValue.type = SomeValue
1 Like

I think you are confusing subtypeable with subclassing.

Every value has many types. As such, its type can be a subtype of many other types.

For example, lets check the number 5.
That value has the following types (probably more).

val fiveSingletonType: 5 = 5
val intType: Int = 5
val anyValType: AnyVal = 5
val anyType: Any = 5

All those will typecheck, and always the previous is a subtype of the following, That is the reason we can assign it.

You can read this for more information.


PS: Is there a way to move this to the correct discourse?

@BalmungSan wrote:

I think you are confusing subtypeable with subclassing .

No, I don’t. These two terms are different.

Every value has many types. As such, its type can be a subtype of many other types.

So, an object’s type is a subtype of other types, yet it makes sense.

What doesn’t make sense is that an object can extend a class because it would imply that an object as value is a subtype of a class which implies an object is also a class and therefore not a value.

But maybe extends has different meanings for different entities.

You can read this for more information.

I doesn’t describe the semantics of object very well.

PS: Is there a way to move this to the correct discourse?

I have no problem with this, but it would be good feat if this is done by the admins directly in order to see your answers made in this thread.

an object can extend a class because it would imply that an object as value is a subtype of a class.

You can never be a subtype of a class, classes and types are completely different things. types exist at compile time, classes exists in the JVM runtime.

When you define a class A or a trait B you are also defining types with the same names.
The link that I provided contains a more in deep discussion about that.

And finally, as I said, you can consider the object keyword as a shortcut to create a class and an unique instance of that class. Just that the name that you give to the object is the name of the value not the name of the class*.
It is just the singleton pattern embedded in the language.

Yes, extends has different meanings. If we assume that class X extends Y is already well defined, then object A extends B means that there’s value A of some anonymous class and that anonymous class extends class B.

1 Like

@BalmungSan wrote:

When you define a class A or a trait B you are also defining types with the same names.
The link that I provided contains a more in deep discussion about that.

Okay, I think I get that point.

And finally, as I said, you can consider the object keyword as a shortcut to create a class and an unique instance of that class .

This is what I see in the repl, object A is of type A in (with :type in dotr )

@tarsa wrote:

Yes, extends has different meanings. If we assume that class X extends Y is already well defined, then object A extends B means that there’s value A of some anonymous class and that anonymous class extends class B .

Thanks, it would be nice if this is documented somewhere.

This is what I see in the repl, object A is of type A in (with :type in dotr )

I haven’t used dotty. Thus, I am not sure if it changed.
But on Scala 2.13, this happens:

scala> trait B

scala> object A extends B
defined object A

scala> :type A
A.type // 'A' has its own type, which is 'A.type'.

scala> implicitly[A.type <:< B]
res: A.type <:< B = generalized constraint // Which is a subtype of 'B' (type).

scala> A.getClass
res0: Class[_ <: A.type] = class A$ // 'A' also has its own class, 'A$'.

scala> A.isInstanceOf[B]
res: Boolean = true // Which is a subclass of 'B' (class).

Also, if you compile the following program with the -print flag.

// Program.scala
trait B
object A extends B

You can see this:

// scalac -print Program.scala
package <empty> {
  abstract trait B extends Object;
  object A extends Object with B {
    def <init>(): A.type = {
      A.super.<init>();
      ()
    }
  }
}

There you can see that A is really a class that extends B.


Thanks, it would be nice if this is documented somewhere.

I think that is kind of documented in many places. But, I agree that the Scala written documentation could be better.
Anyways, see this. At the beginning it states that:

An object is a class that has exactly one instance. It is created lazily when it is referenced, like a lazy val.

An object is a class that has exactly one instance. It is created lazily when it is referenced, like a lazy val.

This sentence from the link cannot make sense regarding an object as value.
I will try to clarify:

(class C).isInstanceOf[Class] where type Class (which is a meta type) contains all classes
(object O).isInstanceOf[?] #where ?.isInstanceOf[Class]

For instance (object O) is an instance of the Object class, then it can’t be an instance of Class because Object is an instance of Class.

InstanceOf relationships aren’t transitive.

So if one states an object is a Class, then (object O) isInstanceOf[Class] and O can’t be passed to Object for instance, because Object is also an instance of Class, so O can’t be an instance of Object because O is at the same level as Object.

I do understand you from the point of a singleton type, but a singleton type is also a type, so O can’t be a singleton type, otherwise it would be excluded as value?

Personally, I have the feeling that (object O) implies that there is an binding in the value layer with name O and also in the class/type layer with the same name. And the singleton type refers to O in the type/class layer, while the value being passed refers to the name in the value layer.

(class C).isInstanceOf[Class] where type Class (which is a meta type) contains all classes
(object O).isInstanceOf[?] #where ?.isInstanceOf[Class]

This does not make any sense.
First, class C is a declaration of a new class, you can not call isInstanceOf (nor any other thing) in it, it is not a value. (Something similar applies to object O).
Second, your meta class is Any, if you are referring to the superclass of all classes.
Third, if ? is a value (given you said ?.isInstanceOf[Class]) then you can not said x.isInstanceOf[?], you can not ask if a value is an instance of another value, you can only check if a value is an instance of a class. And that is a runtime check.

InstanceOf relationships aren’t transitive.

It depends on what you mean with transitive. Given that the left operand of isInstanceOf is a value and the right one is a class. You can not really create a transitive relationship (in the formal sense of the word). But, you can check this:

 trait A extends Any
 trait B extends A
 object C extends B

 C.isInstanceOf[B] // true
 (new B {}).isInstanceOf[A] // true
 C.isInstanceOf[A] // true
 C,isInstanceOf[Any] // true

And any other check that you want to perform will be true, as long as the right side is a superclass of the value in the left.
And this applies to everything in general, not just to objects. For example:

5.isInstanceOf[Int] // true.
5.isInstanceOf[Any] // true.

So if one states an object is a Class, then (object O) isInstanceOf[Class] and O can’t be passed to Object for instance, because Object is also an instance of Class, so O can’t be an instance of Object because O is at the same level as Object.

Sorry but, I simply do not understand what do you meant here.

I do understand you from the point of a singleton type, but a singleton type is also a type, so O can’t be a singleton type, otherwise it would be excluded as value?

Personally, I have the feeling that (object O) implies that there is an binding in the value layer with name O and also in the class/type layer with the same name. And the singleton type refers to O in the type/class layer, while the value being passed refers to the name in the value layer.

When you do object B extends A, you are:

  • Creating a class B$ that extends the class A.
  • Creating a type B.type that is a subtype of the type A.
  • Creating a value B which is an instance of B$ and of type B.type.

All these three exists in different moments and namespaces.
types only exist in compiletime & classes only exist in the JVM runtime.

That is not so much different that a normal class.
For example when you do class B extends A and then val b = new B. You are:

  • Creating a class B that extends the class A.
  • Creating a type B. that is a subtype of the type A.
  • Creating a value b which is an instance of B and of type B.

As you can see, there are only some naming differences, due the implementation internal details.
But that is all, an object is just a singleton.


Anyways, if you still have questions. I think it would be better if you move the discussion to gitter. There you will get a more interactive experience, and there are many more people that may help you.

1 Like

Man, a visual representation of this would be so very helpful.

1 Like

please move to users.scala-lang.org