1 00:00:00,230 --> 00:00:04,590 During the initialization process, at times we may need to call on 2 00:00:04,590 --> 00:00:09,320 other initializers in a process known as initializer delegation. 3 00:00:09,320 --> 00:00:13,470 We've sort of seen what this looks like, because when initializing subclasses, 4 00:00:13,470 --> 00:00:17,980 we've called super init to delegate initialization of a base class. 5 00:00:17,980 --> 00:00:21,390 Initializer delegation is a bit more extensive than that, and 6 00:00:21,390 --> 00:00:25,840 differs based on whether using a value type or a reference type. 7 00:00:25,840 --> 00:00:28,031 Let's try and cover all our bases, and 8 00:00:28,031 --> 00:00:32,028 we'll start on the simple end by looking at value types using a struct. 9 00:00:32,028 --> 00:00:35,905 So, let's add a new comment, 10 00:00:35,905 --> 00:00:41,136 Initializer Delegation- Value Types. 11 00:00:43,233 --> 00:00:46,740 So really quick, let's define an example that we've seen before. 12 00:00:46,740 --> 00:00:54,848 So we have a struct Point that has an x and y value. 13 00:00:54,848 --> 00:01:01,853 We also have a struct Size that has a width with a default value and 14 00:01:01,853 --> 00:01:06,300 a height with a default value, as well. 15 00:01:06,300 --> 00:01:13,200 And then finally we have a struct Rectangle that has an origin 16 00:01:14,950 --> 00:01:19,540 of type Point as a default value, and size. 17 00:01:22,060 --> 00:01:26,970 Since origin and size here in the rectangle have default values, 18 00:01:26,970 --> 00:01:31,280 we can easily create an instance of rectangle without needing to assign values 19 00:01:31,280 --> 00:01:32,910 by just doing that. 20 00:01:32,910 --> 00:01:38,100 Now because Rectangle is a struct, we also have a memberwise initializer 21 00:01:38,100 --> 00:01:42,330 that we can use, as you can see right here, to assign different values. 22 00:01:42,330 --> 00:01:45,536 Instead let's go ahead and instead of relying on the automatic one, 23 00:01:45,536 --> 00:01:48,010 let's write out the memberwise initializer. 24 00:01:48,010 --> 00:01:55,681 So it's init with origin of type Point and size of type Size. 25 00:01:55,681 --> 00:01:57,105 And then inside, pretty simple. 26 00:01:57,105 --> 00:02:00,880 We'll just assign those values over to the stored properties. 27 00:02:02,730 --> 00:02:04,160 This initializer is useful, 28 00:02:04,160 --> 00:02:08,120 but the arguments that we're passing in here are custom types, Point and 29 00:02:08,120 --> 00:02:13,010 Size, which means they need to be constructed outside of the initializer. 30 00:02:13,010 --> 00:02:16,000 We've alluded to this in the past, but both value and 31 00:02:16,000 --> 00:02:19,400 reference types can contain more than one initializer. 32 00:02:19,400 --> 00:02:22,550 We've never written a second init method before because, well, 33 00:02:22,550 --> 00:02:24,128 we didn't really need to. 34 00:02:24,128 --> 00:02:27,130 But here I'd like to write one that simply takes the values 35 00:02:27,130 --> 00:02:31,390 we need to construct origin and size, and then does the work inside the init method. 36 00:02:31,390 --> 00:02:37,244 So right below this initializer, we'll say init with an x and 37 00:02:37,244 --> 00:02:44,015 a y value for the Point, and then a height and a width value for the Size. 38 00:02:44,015 --> 00:02:47,876 Now inside we can use these values to construct an instance of Point and 39 00:02:47,876 --> 00:02:51,200 Size inside the initializer and hide the work. 40 00:02:51,200 --> 00:02:54,832 So we'll say let origin = Point. 41 00:02:54,832 --> 00:02:59,405 We'll use the memberwise there and we'll say x and y. 42 00:02:59,405 --> 00:03:03,909 And we'll do the same for size, we'll use the memberwise initializer on 43 00:03:03,909 --> 00:03:07,915 the Size struct and we'll pass through the width and the height. 44 00:03:10,065 --> 00:03:12,005 From here, now that we have these two values, 45 00:03:12,005 --> 00:03:14,665 we can assign these values to our stored properties. 46 00:03:14,665 --> 00:03:21,325 We'll say self.origin = origin and self.size = size. 47 00:03:21,325 --> 00:03:23,565 Do you see something interesting going on here though? 48 00:03:23,565 --> 00:03:27,151 Down here we are repeating the code, the exact same lines of 49 00:03:27,151 --> 00:03:30,760 code that we already wrote in our memberwise initializer. 50 00:03:30,760 --> 00:03:34,470 Instead of writing the same code again, instead of rewriting those lines, 51 00:03:34,470 --> 00:03:39,590 how about we delegate initialization from this init method to this one? 52 00:03:39,590 --> 00:03:43,124 So again, rather than writing out those same lines of code, 53 00:03:43,124 --> 00:03:46,049 we'll get rid of this and we'll say self.init. 54 00:03:46,049 --> 00:03:51,360 And then we'll use the initializer we defined earlier, so origin and size. 55 00:03:54,408 --> 00:03:58,530 By calling self.init, we're instructing another initializer 56 00:03:58,530 --> 00:04:02,770 in the same type to finish up the initialization process. 57 00:04:02,770 --> 00:04:07,170 In this way, we can create many initializers that serve custom needs, 58 00:04:07,170 --> 00:04:09,880 different ways to construct the same class. 59 00:04:09,880 --> 00:04:12,080 But rather than all duplicating the work, 60 00:04:12,080 --> 00:04:16,800 we can allow all of the object creation to pass through a single point. 61 00:04:16,800 --> 00:04:17,630 So for example, 62 00:04:17,630 --> 00:04:21,740 this is the single point that we're going to pass the object creation work through. 63 00:04:21,740 --> 00:04:25,400 So this init method just delegates it to the first one. 64 00:04:25,400 --> 00:04:27,150 Here's another initializer, for example. 65 00:04:27,150 --> 00:04:28,122 Instead of origin, 66 00:04:28,122 --> 00:04:32,800 let's say we knew the center of the rectangle that we wanted to define, and 67 00:04:32,800 --> 00:04:36,772 the size, and we want to create an instance using just that information. 68 00:04:36,772 --> 00:04:40,260 So we'll create an init method that takes a center of type Point 69 00:04:40,260 --> 00:04:45,020 rather than an origin, and a size of type Size. 70 00:04:45,020 --> 00:04:50,005 And then inside the init method, we can use those values to 71 00:04:50,005 --> 00:04:54,075 figure out where the origin's x value will be, 72 00:04:54,075 --> 00:04:57,667 which is center.x- size.width/2. 73 00:04:57,667 --> 00:05:03,479 And same thing for the origin's y value, but this time we use the center's y value. 74 00:05:03,479 --> 00:05:08,753 And deduct the rectangle's height divided by two, so half the height. 75 00:05:08,753 --> 00:05:12,880 Using these two values we just calculated, we can define an origin. 76 00:05:12,880 --> 00:05:20,010 So Point originX and originY. 77 00:05:20,010 --> 00:05:23,285 And then again, rather than writing out the same lines of code, 78 00:05:23,285 --> 00:05:26,930 we'll delegate the work to that first initializer. 79 00:05:26,930 --> 00:05:31,630 So we'll pass in the origin, and the size. 80 00:05:32,880 --> 00:05:33,730 By delegating, 81 00:05:33,730 --> 00:05:38,280 we can use an initializer that already provides the functionality we need. 82 00:05:38,280 --> 00:05:40,050 We avoid repeating code. 83 00:05:40,050 --> 00:05:41,280 Pretty simple, right? 84 00:05:41,280 --> 00:05:43,140 Well, that's for value types. 85 00:05:43,140 --> 00:05:46,770 Reference types, on the other hand, are a completely different beast. 86 00:05:46,770 --> 00:05:48,200 Let's check it out in the next video.