<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div><blockquote type="cite" class=""><div class="">On Apr 8, 2017, at 5:22 AM, Hugo Lundin via swift-users &lt;<a href="mailto:swift-users@swift.org" class="">swift-users@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><pre class="" style="font-size: 9pt; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); font-family: Menlo;"><pre class="" style="font-family: Menlo; font-size: 9pt;">How would I be able to achieve this in Swift? My current idea of this approach does not seem to work, but also the idea to create specific subclasses for every type (and then type cast the different properties), gives a lot of work, and there would be a limitation for which types are available. </pre></pre></div></blockquote></div><div>I would create a protocol with the same interface (other than initializers) as your `Property` type, but with an `Any` equivalent to any `T`-taking API. Then make your `Array` use the protocol, not `Property` itself, as its element type.</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>// Let's say this is your existing type:</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>struct Property&lt;T&gt; {</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>let description: String</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>let property: T</div><div><span class="Apple-tab-span" style="white-space:pre">                </span></div><div><span class="Apple-tab-span" style="white-space:pre">                </span>init(description: String, property: T) {</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>self.description = description</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>self.property = property</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>// Create a protocol equivalent that doesn't use T:</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>protocol AnyProperty {</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>var description: String { get }</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>var anyProperty: Any { get }</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">        </span></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>// Then conform `Property` to it:</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>extension Property: AnyProperty {</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>var anyProperty: Any {</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>return property</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">        </span></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>// Now, in your Analytics class:</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>class Analytics {</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>private&nbsp;var properties: [AnyProperty]</div><div><span class="Apple-tab-span" style="white-space:pre">                </span></div><div><span class="Apple-tab-span" style="white-space:pre">                </span>func add(_ property: AnyProperty) {</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>properties.append(property)</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">                </span></div><div><span class="Apple-tab-span" style="white-space:pre">                </span>func show() {</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>for p in properties {</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>print("\(p.description): \(p.anyProperty)")</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>// And do:</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>let stats = Analytics()</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>stats.add(Property(description: "HealthKit", property: false))</div><div><div><span class="Apple-tab-span" style="white-space: pre;">        </span>stats.add(Property(description: "iOS Version", property: "9.3"))</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>stats.show()</div><div class=""><br class=""></div><div class="">This is called "type erasure"; we say that the `AnyProperty` protocol is "erasing" the type of the `T` generic parameter because it essentially hides it behind the protocol. Java automatically erases all type parameters, which is convenient here, but it can lead to bugs. (For instance, the generic parameter of `List` is similarly erased, so you can cast a `List&lt;Property&gt;` up to `List&lt;Object&gt;`, then add non-`Property` objects to it. When you later run `show()`, it will throw an exception.) Swift is more strict, which prevents bugs but sometimes means you need to explicitly erase types.</div><div class=""><br class=""></div><div class="">Here we've used a protocol to erase the type of `Property`, but that often isn't an option—for instance, when you cast an instance to a protocol type, the "wrapper" around it doesn't itself conform to any protocols. When it isn't, you have to make a more complicated type-erasing wrapper—usually either by making a closure that calls each method and storing them in properties, or by writing a non-generic abstract superclass which declares all the visible members and a generic subclass that overrides the superclass declarations.</div><div class=""><br class=""></div><div class="">Here's an article on how to write type-erased wrappers in more complicated situations:&nbsp;&lt;<a href="https://www.bignerdranch.com/blog/breaking-down-type-erasures-in-swift/" class="">https://www.bignerdranch.com/blog/breaking-down-type-erasures-in-swift/</a>&gt;</div></div><div class=""><br class=""></div>Hope this helps,<br class=""><div class="">
<span class="Apple-style-span" style="border-collapse: separate; font-variant-ligatures: normal; font-variant-east-asian: normal; font-variant-position: normal; line-height: normal; border-spacing: 0px;"><div class=""><div style="font-size: 12px; " class="">--&nbsp;</div><div style="font-size: 12px; " class="">Brent Royal-Gordon</div><div style="font-size: 12px; " class="">Architechies</div></div></span>

</div>
<br class=""></body></html>