Having Unassigned type alias inside a class

Going through this; you can see in the definitions of MList that there is an uninitialised type alias inside the class. I am having a tough time comprehending it.

class MyClass{
type A

class AnotherClass

All of these compile

val a : MyClass {type A = String} = new MyClass(){type A = String} //Why should we use the keyword again. Why not MyClass {A= String}?

val a : MyClass = new MyClass() // What is the value (rather type) of A

val a : AnotherClass {type A = String} = null //There is no type A defined inside AnotherClass. How does it still compile?

I am pretty sure that I have it all wrong. Would like to be steered in the right direction. Thanks :slight_smile:

What X = Y should mean? You need to specify whether it’s type, val, def or something else. There’s nothing stopping you from having a def A or val String:

class A {
  val String = 5
  def A = String
val A = new A
println(A.A) // prints 5

You can’t do new A if A can’t be statically resolved to a concrete type.

Because AnotherClass (even with a refinement) is a subtype of AnyRef and Null is a subtype of all AnyRef subtypes: https://docs.scala-lang.org/tour/unified-types.html

I didn’t know we could do this! Always thought that Int, String etc were keywords and that we cannot use them as variable name. The more I code in Scala the more I realise that I don’t know shit.

And there is a mistake in this
val a : A = new A() //What is the value (rather type) of A

I intended to write
val a : MyClass = new MyClass() // What is the value (rather type) of A

Have edited the question as well.

Int and String are just type names. In fact it’s possible to have value and type of the same name in the same scope (and that’s often encountered):

class X // defined type named X
object X // defined value named X
val a : MyClass = new MyClass() // What is the value (rather type) of A

You can’t do new MyClass if MyClass is a trait or an abstract class. Non-abstract class can’t have an abstract type member. Thus every time you instantiate a class using new, all type members are concrete (non-abstract). This is very similar to generic type parameters.

Note that if you have:

abstract class MyClass {
  type A

then following code doesn’t compile:

val x: MyClass = new MyClass { type A = String }
new x.A()

but this does:

val x = new MyClass { type A = String }
new x.A()

That’s because it’s equivalent to:

val x: MyClass { type A = String } = new MyClass { type A = String }
new x.A()

because refinements from anonymous classes go to inferred type.