Is eg Int.self a metatype?

In Xcode 7 beta 2, we'll get the following new compile time error:

let MyIntSomething = Int.self
let b = MyIntSomething(123) // Error: Initializing from a metatype must reference 'init' explicitly
// let b = MyIntSomething.init(123) // (So this will work.)


And/but according to the iBook:

A metatype referes to the type of any type, including class types, structure types, enumeration types, and protocol types. /.../ You can use the postfix self expression to access a type as a value. For example, SomeClass.self returns SomeClass itself, not an instance of SomeClass.


If MyIntSomething is the Int type itself (as the iBook says), why can't we do this:

let b: MyIntSomething = 123

?


And if it is a metatype (as the error message says) why doesn't the iBook say anything about SomeType.self returning a metatype and instead says it returns the type itself as a value (and also it says nothing about type objects as the beta 2 release notes does in relation to this)?


I'd like to know what MyIntSomething is. Is it a metatype (as the error message says) or is it the Int type itself (as the iBook says) or is it both?


Or/and is it a type object as opposed to a type name, if so what is the difference?


Where can I get some more substantial information about all this, preferably with lots of interesting use cases?

This is the way I think of it...


Metatypes are a broad category of things, similar to "functions".


Swift doesn't allow you to create a variable of type 'func' which can hold any type of function, but you can make a variable which holds functions with a particular signature.

func test1() -> String {return "1"}
func test2() -> String {return "dkfjefjdslfjdslk"}
func test3(a: String) -> String {return a}

var method = test1
method = test2

method = test3  //error: cannot assign a value of type '(String) -> String' to a value of type '() -> String'


Similarly, you can't create a variable of type 'Metatype' to hold any type, but you can make a variable which holds a particular 'type object'.

var type: Int.Type = Int.self


That variable can't hold other type objects, though:

var type2 = Int.self

type2 = Float.self // error: cannot assign a value of type 'Float.Type' to a value of type 'Int.Type'



The reason why the following doesn't really work

let MyIntSomething = Int.self
let b: MyIntSomething = 123

is because MyIntSomething is a variable/object that exists in the runtime, and not a type-definition that the compiler can use.

/.../ is because MyIntSomething is a variable/object that exists in the runtime, and not a type-definition that the compiler can use.


I'm not sure I understand what you mean by that. According to the Xcode 7 beta 2 release notes, there seems to be both "static type objects" and "dynamic type objects". In my example below, the compiler clearly knows enough about MyIntSomething to be able to statically decide that the function call on line 4 is ok:

func compileTimeErrorUnlessCompilerKnowsThisIsGivenAnInt(x: Int) { print(x) }
let MyIntSomething = Int.self
let b = MyIntSomething.init(123)
compileTimeErrorUnlessCompilerKnowsThisIsGivenAnInt(b) // No compile time error.

So I guess MyIntSomething is a "static type object" ...

as well as a metatype (according to the error message in my above post) ...

as well as the "Int type itself (as a value)" (according to the iBook) ...

It turns out I was wrong about being able to make a variable that holds arbitrary type objects, since this works:

var type2: Any.Type = Int.self
type2 = Float.self


But that variable could only be used to access type methods and initializers that belong to Any.



I'm not sure how using a type-object variable as an explicit type in your code would be useful.


If you create a type-object variable from a parameter to a function using .dynamicType, the compiler uses the explicit type from the parameter to decide which kind of type object your variable will hold, and only type methods and intializers available from that explicit type will be available.


For example:

func testTypes(a: CustomStringConvertible) -> String
{
    var aType = a.dynamicType   // variable of type CustomStringConvertible.Type, holding Int.Type
  
    let z = aType.init() // error: 'CustomStringConvertible.Type' does not have a member named 'init'
  
    return "aType is a \(aType)"
}


So there doesn't seem like there would be any advantage to using the variable name as an explicit type in the code (since it is just the same as the explicit type of the parameter, or in the case of MyIntSomething the same as the explicit type you created it from).

Is eg Int.self a metatype?
 
 
Q