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
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.
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
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.