In Swift we are able to write following construction:
class SomeClass {}
let metaMetatype: SomeClass.Type.Type = SomeClass.Type.self
Here metaMetatype does not conform to type AnyObject (SomeClass.Type does). Construction can be even longer, as long as we wish:
let uberMetatype: SomeClass.Type.Type.Type.Type.Type.Type.Type.Type.Type.Type = SomeClass.Type.Type.Type.Type.Type.Type.Type.Type.Type.self
Are this constructions have any sense? If SomeClass.Type.Type not an object, what is this, and why we able to declare it?
If SomeClass.Type.Type not an object, what is this and why we able to declare it?
I will try to dissect what you're asking.
SomeClass.Type.Type is a Metatype of a Metatype. Metatypes exist in Swift because Swift has types that are not classes. This is most similar to the Metaclass concept in Objective-C.
Lexicon.rst in the Swift Open Source Repo has a pretty good explanation:
metatype
The type of a value representing a type. Greg Parker has a good
explanation of Objective-C's "metaclasses" because Swift has types
that are not classes, a more general term is used.
We also sometimes refer to a value representing a type as a "metatype
object" or just "metatype", usually within low-level contexts like IRGen
and LLDB. This is technically incorrect (it's just a "type object"), but
the malapropism happened early in the project and has stuck around.
Why are we able to declare a type of a type of a type... and so on? Because it's a feature of the language called type metadata:
type metadata
The runtime representation of a type, and everything you can do with it.
Like a Class in Objective-C, but for any type.
Note that you can't do something like NSObject().class in Swift because class is a reserved keyword for the creation of a class. This is how you would get the type (or class in this case) of an NSObject in Swift:
let nsObj = NSObject()
nsObj.classForCoder // NSObject.Type
nsObj.classForKeyedArchiver // NSObject.Type
nsObj.dynamicType // NSObject.Type
Note that nsObj and nsObj.self are identical and represent the instance of that NSObject.
I don't see where in the Swift module or open source repo where types allow for .Type, but I'm still looking. It might have to do with the inheritance from SwiftObject, the Objective-C object all Swift classes inherit from (at least on Mac).
Type of a class is also represented in memory (it has for example their own methods). It's represented by singleton representing the Type. (It's not an instance of this type - that's something different). If you call self on a Type like this SomeClass.self you will take singleton instance representing the SomeClass Type.
For more info check this answer
Related
Is there an equivalent in Swift to pass as an argument an empty interface{} like in Go?
I am not very familiar with Go, but I think the Swift equivalent would be an argument of type Any or AnyObject. You can't do much with such an argument other than try to cast it to a more specific type.
Go's interfaces and Swift's protocols are quite different:
Golang's interfaces are "structural" (akin to C++'s "Concepts"), meaning that their identity is defined by their structure. If a go struct has the structure required by an interface, it implicitly implements that interface. That is, the struct doesn't say anywhere "I am strust S, and I implement interface I."
Swift's protocols are "nominal", meaning that their identity is defined their name. If a Swift struct fulfills all of the requirements of a protocol, it doesn't conform to that protocol, unless an explicit struct S: P { ... } declaration is made (the body of that declaration can even be empty, but it's still necessary for the conformance to exist).
The closest analogue to interface{} in Swift is Any. It's built-in protocol to which all type conform. It gets special treatment, it's defined by the compiler, and has hard-coded logic to make all other types conform to it. You won't see protocol Any {} or struct S: Any {} declared anywhere explicitly. AnyObject is similar, and also gets special treatment. But no other Swift protocols do. Their conformance need to be explicit.
If I am not mistaking Swift's equivalent would be:
protocol EmptyProtocol {
}
In swift interfaces are called protocols don't ask me :D
Are you trying to do type erasure or something? Just curious...
In Apple documentation of NSXPCInterface.setClasses(_:for:argumentIndex:ofReply:), for Swift, the first parameter is described as:
An NSSet containing Class objects —for example, [MyObject class].
Hmmm, it looks as though someone neglected to update this from Objective-C to Swift. For Swift I presume it should be something like
A Set containing Class Types
(Someone please correct my wording.) But how do you make a Set containing Class Types? The compiler will not allow me to declare a Set whose member types are not do not conform to Hashable. This makes sense because hashes are needed to maintain uniqueness among members. But Class Types in Swift do not seem to be hashable. Try this in any Swift file, or a playground…
class Foo {}
let mySet: Set<AnyHashable>
mySet.insert(Foo)
The compiler complains:
Argument type 'Foo.Type' does not conform to expected type 'Hashable'
Or, more broadly, does anyone know how to use NSXPCInterface.setClasses(_:for:argumentIndex:ofReply:) in Swift 5?
The classes you pass need to be #objc classes (and subclasses of NSObject). You'll put them into an NSSet, and then cast that to Set:
let classSet = NSSet(object: Foo.self) as! Set<AnyHashable>
This is almost certainly a bug in NSXPCInterface (it needs some kind of "refine for Swift" or possibly a shim), and I suggest opening a defect at bugreport.apple.com.
As of Swift v5.6 (perhaps earlier), you can create the set without casting:
let classSet = NSSet().adding(Foo.self)
This is because adding() is declared like this:
open func adding(_ anObject: Any) -> Set<AnyHashable>
I am reading about LiteralConvertible protocols (lets take StringLiteralConvertible for example), and I found that in swift 1.2 you can use implicit typecasting from literal to your custom LiteralConvertible type. Following example taken from NSHipster blog:
struct SomeStruct: StringLiteralConvertible {
init(stringLiteral value: String) {}
init(extendedGraphemeClusterLiteral value: String) {}
init(unicodeScalarLiteral value: String) {}
func someFunc(){}
}
Somewhere in executable space:
let someStruct: SomeStruct = "😀"
someStruct.someFunc() // ok
("😃" as SomeStruct).someFunc() // ok
"😂" is SomeStruct // ok (always true warn)
"😡".someFunc() // error: value of type 'String' has no member 'someFunc'
Comments are for swift 2 compiler. Seems like there was no error in swift 1.2. Am I missing something or there is no way to achieve this behavior in swift 2?
It wouldn't make sense, w.r.t. type safety and non-ambiguity, if the last row ("😡".someFunc()) could resolve to just any kind of type that happens to conform to StringLiteralConvertible and have instance an function someFunc {}. Protocols cannot know (without explicit testing) which types conform to them, but rather, are used e.g. as type constraint to test if a given type conforms to the protocol. What if we have another type SomeStruct2: StringLiteralConvertible { ... } that also implements someFunc(), how would the compiler resolve the call "😡".someFunc() if the implicit type conversion you describe were to to be allowed?
W.r.t. to the concept working in Swift 1.2: Swift 1.2 is ancient in terms of a fast growing (up) language as Swift, so there are bound to be some peculiarities in Swift 1.2 that seems really strange in term of "modern Swift". Just as custom conversion methods (__conversion() function), implicit typecasting is a concept that is not entirely agreeable with a statically typed and safe language such as Swift.
To somewhat base this answer on official sources, we may take a look at Swift evolution proposal SE-0072:
SE-0072: Fully eliminate implicit bridging conversions from Swift
This proposal relates to the implicit bridging between Swift native and Obj-C types, but the Swift team's position w.r.t. to any implicit conversions is made quite clear in the description of the accepted proposal [emphasis mine]
In Swift 1.2, we attempted to remove all implicit bridging conversions
from the language.
...
In the interest of further simplifying our type system and our user
model, we would like to complete this work and fully remove implicit
bridging conversions from the language in Swift 3.
...
I propose that we fully eliminate implicit bridging conversions in
Swift 3. This would mean that some users might have to introduce more
explicit casts in their code, but we would remove another special case
from Swift's type system and be able to further simplify the compiler.
The question popped in my head, what is happening when I define a Swift type alias? What is the mechanism behind it? Until I learned the Automatic Initializer Inheritance chapter from the Swift official document:
If your subclass doesn't define any designated initializer, it automatically inherits all of its superclass designated initializers
And here is my practice code for learning
class Vehicle{
var numberOfWheels = 0
var description: String {
return "\(numberOfWheels) wheel(s)"
}
}
class Auto: Vehicle{}
let VM = Auto()
VM.numberOfWheels
Wow! this works,at least performs, exactly as the Swift type alias. Auto is the alias of the type Vehicle
Question: Am I understand it right? This is the mechanism behind type alias.
Question: Am I understand it right? This is the mechanism behind type alias.
NO, typealises and subclassing (with inheriting all methods and initializers) are different things and based on different semantics and mechanisms.
let v1 = Vehicle()
v1 is Auto //->false
typealias Norimono = Vehicle
v1 is Norimono //->true (with warning "'is' test is always true)
The last result (including the warning you may find) is exactly the same as v1 is Vehicle.
Typealias is literally an alias, it's giving another name for the same type.
One more, you can define typealias of structs or enums, which you cannot define inherited classes (types).
Not really, but if you've never seen object oriented programming they could look somewhat similar, i agree.
Auto is a subclass that extends the original vehicle and could add additional properties and method to the Vehicle even if in that example it doesn't do it.
Auto and Vehicle are not the same thing, a Vehicle is a basic type and and Auto is one of its subtypes, what you can do with a Vehicle you can do with an Auto but not vice-versa.
A typealias is just an alias, a way to give and additional "name" to a pre-existing type, just that. A type and his alias are the same thing.
This question already has answers here:
Why Choose Struct Over Class?
(17 answers)
Closed 7 years ago.
I learn Swift from some time, I know the differences between structure and class. The main difference is structure is of value type and class is of reference type but didn't understand when to use structure instead of a class. Please explain it.
For example, In case of Protocols:
First, We have just a protocol of struct type:
protocol SomeProtocol{
func doSomeStuff()
}
Second, We make protocol of class type like this:
protocol SomeProtocol: class{
func doSomeStuff()
}
So, Please explain me, when we have to use protocol of struct type or of class type.
Firstly structs are passed by value (copied), and a class is passed by reference (copied just the memory address to the object).You may want to use structs for simpler types, because you get a free init for all the properties your struct has.And with protocols, the first one you can use it on class,struct and enum, the second you say that you only use that on classes,and you may want to put class if your protocol is a delegate or a data source,because you want the property(of the type of your protocol) weak to avoid the memory cycle. IMHO use classes for multi-scene apps because you don't need to take care to update value when you edited something in an another scene.
The protocol is not "of struct type" or "of class type", that is wrong terminology.
If you write SomeProtocol: class you make sure only classes can conform to that protocol, structs cannot. If you don't include the class both classes and structs can conform.
The docs (scroll down to "Class-Only Protocols") tell you that
You can limit protocol adoption to class types (and not structures or enumerations) by adding the class keyword to a protocol’s inheritance list. The class keyword must always appear first in a protocol’s inheritance list, before any inherited protocols.
Use a class-only protocol when the behavior defined by that protocol’s requirements assumes or requires that a conforming type has reference semantics rather than value semantics. For more on reference and value semantics, see Structures and Enumerations Are Value Types and Classes Are Reference Types.