{"id":130,"date":"2016-02-12T23:25:20","date_gmt":"2016-02-12T23:25:20","guid":{"rendered":"http:\/\/thibaultklein.com\/ios\/?p=130"},"modified":"2017-06-03T12:11:51","modified_gmt":"2017-06-03T12:11:51","slug":"associated-types-in-swift","status":"publish","type":"post","link":"https:\/\/thibaultklein.com\/ios\/associated-types-in-swift\/","title":{"rendered":"Associated Types in Swift"},"content":{"rendered":"<h2>Context<\/h2>\n<p>When working on Swift protocols, you might need to use generic types as a variable. Swift compiler can understand when you provide a protocol as a variable, but what if you want to use a type? Here is an example of implementing a data structure based on protocols.<\/p>\n<pre><code>protocol A {\n\n}\n\nprotocol B {\n    var a: A { get }\n}\n\nstruct myStructA: A {\n\n}\n\nstruct myStructB: B {\n    var a: myStructA\n}\n<\/code><\/pre>\n<p>By using <code>myStructA<\/code> for the variable <code>a<\/code> Xcode will complain because <code>myStructB<\/code> doesn\u2019t conform to protocol <code>B<\/code>. The reason is that Swift compiler is expecting a type <code>A<\/code> and can\u2019t figure that <code>myStructA<\/code> is conforming to <code>A<\/code>. A solution would be to change the type of <code>a<\/code> in <code>myStructB<\/code> to <code>A<\/code>, but then what if you want to use <code>myStructA<\/code> and use custom features that you didn\u2019t declare in protocol <code>A<\/code>?<\/p>\n<p>That\u2019s where <em>associated types<\/em> become handy.<\/p>\n<p>Unlike classes, structs and enums, protocols don\u2019t support generic type parameters but abstract type members. In Swift they are known as associated types.<\/p>\n<p>Cf Apple:<\/p>\n<p><i>&#8220;When defining a protocol, it is sometimes useful to declare one or more&nbsp;associated types&nbsp;as part of the protocol\u2019s definition. An associated type gives a placeholder name (or&nbsp;alias) to a type that is used as part of the protocol. The actual type to use for that associated type is not specified until the protocol is adopted. Associated types are specified with the&nbsp;typealias&nbsp;keyword.&#8221;<\/i><\/p>\n<p>That said, let\u2019s refactor our previous example using an associated type.<\/p>\n<pre><code>protocol A {\n\n}\n\nprotocol B {\n    associatedtype AType: A\n    var a: AType { get }\n}\n\nstruct myStructA: A {\n\n}\n\nstruct myStructB: B {\n    typealias AType = myStructA\n    var a: AType\n}\n<\/code><\/pre>\n<p>By defining an associated type over <code>protocol A<\/code> we are able to specify to the compiler a placeholder for the type. It is in the protocol implementation that we specify the final type, which gives us the possibility to manipulate a struct object. If your <code>myStructA<\/code> object contains extra features than what is available in <code>protocol A<\/code> you will be able to access them.<\/p>\n<p>You will notice that as soon as you start using associated types in a protocol, you have to use Swift generics everywhere.<\/p>\n<p>This implementation will not compile anymore:<\/p>\n<pre><code>func myFunc(b: B) {\n\n}\n<\/code><\/pre>\n<p>You have to use Swift generics:<\/p>\n<pre><code>func myFunc&lt;T: B&gt;(b: T) {\n\n}\n<\/code><\/pre>\n<p>Because you specified an associated type, that type is not specific enough to be used as a proper type. You have to use the generic syntax to tell the compiler what type is expected in your function.<\/p>\n<h2>Conclusion<\/h2>\n<p>Currently associated types are your only option if you have generic types in your protocols and you want to use an implementation. They are very easy to use and will give you the flexibility to write powerful and cleaner code.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Context When working on Swift protocols, you might need to use generic types as a variable. Swift compiler can understand when you provide a protocol as a variable, but what if you want to use a type? Here is an example of implementing a data structure based on protocols. protocol A { } protocol B&hellip; <a class=\"more-link\" href=\"https:\/\/thibaultklein.com\/ios\/associated-types-in-swift\/\">Continue reading <span class=\"screen-reader-text\">Associated Types in Swift<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[3],"tags":[],"class_list":["post-130","post","type-post","status-publish","format-standard","hentry","category-ios","entry"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p6mZvu-26","jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/thibaultklein.com\/ios\/wp-json\/wp\/v2\/posts\/130","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/thibaultklein.com\/ios\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/thibaultklein.com\/ios\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/thibaultklein.com\/ios\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/thibaultklein.com\/ios\/wp-json\/wp\/v2\/comments?post=130"}],"version-history":[{"count":2,"href":"https:\/\/thibaultklein.com\/ios\/wp-json\/wp\/v2\/posts\/130\/revisions"}],"predecessor-version":[{"id":214,"href":"https:\/\/thibaultklein.com\/ios\/wp-json\/wp\/v2\/posts\/130\/revisions\/214"}],"wp:attachment":[{"href":"https:\/\/thibaultklein.com\/ios\/wp-json\/wp\/v2\/media?parent=130"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/thibaultklein.com\/ios\/wp-json\/wp\/v2\/categories?post=130"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/thibaultklein.com\/ios\/wp-json\/wp\/v2\/tags?post=130"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}