{"id":9030,"date":"2023-12-08T21:38:22","date_gmt":"2023-12-08T21:38:22","guid":{"rendered":"http:\/\/putridparrot.com\/blog\/?p=9030"},"modified":"2023-12-08T21:38:22","modified_gmt":"2023-12-08T21:38:22","slug":"swift-protocols-structs-and-classes","status":"publish","type":"post","link":"https:\/\/putridparrot.com\/blog\/swift-protocols-structs-and-classes\/","title":{"rendered":"Swift Protocols, Structs and Classes"},"content":{"rendered":"<p><em>Note: I\u2019m going through draft posts that go back to 2014 and publishing where they still may have value. They may not be 100% upto date but better published late than never.<\/em><\/p>\n<p><strong>Introduction<\/strong><\/p>\n<p>Protocols can be thought of as similar to interfaces within languages such as C# and Java, hence are used to declare expectations for implementations and can be returned or accepted as params.<\/p>\n<p>We declare a protocol in the following way<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nprotocol Person {\r\n  var firstName: String { get }\r\n  var lastName: String { get }\r\n  var age: Int { get }\r\n}\r\n<\/pre>\n<p>So we can create our implementation of this procotol like this<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nstruct PersonImpl : Person {\r\n  var firstName: String\r\n  var lastName: String\r\n  var age: Int\r\n}\r\n<\/pre>\n<p><strong>Structs and Classes<\/strong> <\/p>\n<p>Apple Swift developers seem to prefer value types over reference types, a struct is a value type and class a reference type. They both share many of the same functionality.<\/p>\n<p>Structs do not require an initializer (constructor) as a default initializer is supplied automatically and will expect all non-optional properties to be supplied.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nclass PersonImpl : Person {\r\n  var firstName: String\r\n  var lastName: String\r\n  var age: Int\r\n\r\n  init(firstName: String, lastName: String, age: Int) {\r\n    self.firstName = firstName\r\n    self.lastName = lastName\r\n    self.age = age\r\n  }\r\n}\r\n<\/pre>\n<p>As you can see, <em>init<\/em> is the name of the initializer or what we may view as a constructor. Classes may also have <em>deinit<\/em> is called when Swift deallocates an instance (struct&#8217;s do not have deinit).<\/p>\n<p><strong>Mutations<\/strong><\/p>\n<p>Where we expect changes to the internal data, in other words where a function mutates data we use the <em>mutating<\/em> keyword. If, for example, we add a protocol function<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nfunc incrementAge() -&gt; Void \/\/ same as func incrementAge()\r\n<\/pre>\n<p>By default struct properties cannot be changed by instance method. In such cases we need to include the <em>mutating<\/em> key word, i.e.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nmutating func incrementAge() -&gt; Void\r\n<\/pre>\n<p>So a struct method implementation will now look like this<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nmutating func incrementAge() -&gt; Void {\r\n  age += 1\r\n}\r\n<\/pre>\n<p>Within a class, we don&#8217;t need to mark the method as mutating.<\/p>\n<p><strong>Accessors<\/strong><\/p>\n<p>There are five access levels<\/p>\n<ul>\n<li>Open: This allows proprties, methods, classes etc. to be accessible by anything that imports the module<\/li>\n<li>Public: This allows proprties, methods, classes etc. to be accessible by anything that imports the module<\/li>\n<li>Internal: This is the <em>default<\/em> access level and allows properties, methods, classes etc. to be accessible from the module where they&#8217;re defined only<\/li>\n<li>Fileprivate: Properties and methods can access from code withint he same source file only<\/li>\n<li>Private: The least visible accessor meaning properties methods etc. are only visible within the same file or class etc.<\/li>\n<\/ul>\n<p><strong>is and as<\/strong><\/p>\n<p>Swift has the concept of <em>is<\/em> and <em>as<\/em> pretty much like C#. So we can declare a type as follows<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nlet p: Person = PersonImp(&quot;Scooby&quot;, &quot;Doo&quot;, &quot;12&quot;)\r\n<\/pre>\n<p>Now if we needed to check if the const <em>p<\/em> is a PersonImpl we would use<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nif p is PersonImpl {    \r\n}\r\n<\/pre>\n<p>we could use <em>as<\/em> within the if statement if we wanted as well, for example<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nif let person = p as? PersonImpl {    \r\n}\r\n<\/pre>\n<p>Here we compare and assign in the same line of code using <em>as?<\/em> which basically means the <em>person<\/em> may be nil (if the type cannot be converted to PersonImpl).<\/p>\n<p><strong>Extensions<\/strong><\/p>\n<p>Just like extension classes in C# &#8211; Swift extensions allow us to add functionality to structures, protocols and classes (as well as enumerations).<\/p>\n<p>An extension is defined using the <em>extension<\/em> key word, for example<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nextension String {\r\n  \/\/ add string functionality, for example\r\n  func capitalize() -&gt; String {\r\n    return self&#x5B;0].toUpper() + self.substr(1)\r\n  }\r\n}\r\n<\/pre>\n<p>We can also add constraints to extensions, so for example a Collection extension that <\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nextension Collection where Iterator.Element: Comparable {\r\n  \/\/ add functionality where elements support Comparable\r\n}\r\n<\/pre>\n<p><strong>Equatable<\/strong><\/p>\n<p>A type needs to conform to the Equatable protocol for a type to be comparable using == and !=.<\/p>\n<p><strong>Generics<\/strong><\/p>\n<p>Swift generics look much the same as generics in C++, Java and C# in that we can declare generics on a function like this<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nfunc add&lt;T&gt;(item: T) {\r\n}\r\n<\/pre>\n<p>We can also add constraints to the genric type like this<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nfunc compare&lt;T: Comparable&gt;(a: T, b: T) -&gt; Bool {\r\n}\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Note: I\u2019m going through draft posts that go back to 2014 and publishing where they still may have value. They may not be 100% upto date but better published late than never. Introduction Protocols can be thought of as similar to interfaces within languages such as C# and Java, hence are used to declare expectations [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[286],"tags":[],"class_list":["post-9030","post","type-post","status-publish","format-standard","hentry","category-swift"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/9030","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/comments?post=9030"}],"version-history":[{"count":5,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/9030\/revisions"}],"predecessor-version":[{"id":10321,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/9030\/revisions\/10321"}],"wp:attachment":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/media?parent=9030"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/categories?post=9030"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/tags?post=9030"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}