Fast error with shared array

I have a very simple platform:

protocol MyProtocol {} struct MyType: MyProtocol {} class MyClass <T: MyProtocol> { func myFunction(array: [T]) { if let myArray = array as? [MyType] { println("Double!") } } } let instance = MyClass<MyType>() let array = [MyType(), MyType()] instance.myFunction(array) 

Then he says " MyType is not a subtype of 'T' " in the if let line. Well, I think, however, MyType and T compatible.

When I changed the if let , it really works:

 if let first = array.first as? MyType 

But now I can not drop the array in [MyType] (Of course, I know that this is a static Swift specification).

I wonder what the problem is. My understanding of generics? Or is it a quick language restriction? If so, is there a way to do this?

Thanks in advance.

+5
source share
2 answers

Swift has no built-in behavior for speculatively converting the contents of arrays from one arbitrary type to another. He will do this only for two types, which, as he knows, have a subtype / supertype relationship:

 class A { } class B: A { } let a: [A] = [B(),B()] // this is allowed - B is a subtype of A let b = a as? [B] let a: [AnyObject] = [1,2,3] // this is allowed - NSNumber is a subtype of AnyObject let b = a as? [NSNumber] struct S1 { } struct S2 { } let a = [S1(),S1()] // no dice - S2 is not a subtype of S1 let b = a as? [S2] 

The protocol does not help:

 protocol P { } struct S1: P { } struct S2: P { } let a = [S1(),S1()] // still no good – just because S1 and S2 both conform to P // doesn't mean S2 is a subtype of S1 let b = a as? [S2] 

Your example is basically a variant of this latter. You have an array of type [T] , and you want to pass it to [MyType] . It is important to understand that you do not have an array of type [MyProtocol] . Your generic type T is the specific type that MyProtocol should implement, but it is not the same.

To find out why you cannot just use any type for any other type, try this code:

 protocol P { } struct S: P { } let a: [P] = [S(),S()] let b = a as? [S] 

This will result in a runtime error: "fatal error: BitCast between types of different sizes cannot be insecure." This gives us a clue as to why you can distinguish an array from one reference type to a subtype - its because it is just a bit discarded from one type of pointer to another. This will work for super / subtype classes, but not for arbitrary classes, structures, or protocols, since they have different binary representations.

+4
source

Common to the child type is not a subtype of the same parent type.

[MyProtocol] in Swift actually translates to Array<MyProtocol> (i.e. generic). The same for [MyType] is a shortcut for Array< MyType > . That is why no one directly transfers to another.

+3
source

Source: https://habr.com/ru/post/1214392/


All Articles