Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Swift_Essential_Training.docx
Скачиваний:
7
Добавлен:
25.05.2015
Размер:
683.22 Кб
Скачать

3. Creating Classes

Defining and instantiating classes Определение и создание экземпляра классы

3. Создание классов

- Свифт объектно-ориентированный язык, так что вместо того, чтобы писать длинные процессуальные программы, мы разделим наш код на отдельные классы, определяющие данные и логику, которая принадлежит вместе. Теперь, чтобы определить кто есть кто класс ключевое слово, а затем имя вашего нового класса. Как вы определяете новый тип, мы бы начать ее с заглавной первой буквы. Теперь те из вас, которые приходят из Objective-C будет очень рад знать, что мы не нуждаются в отдельном заголовок и секции реализации больше, это все-в-одном. Вся наша определение класса содержится внутри этих фигурных скобках.

В настоящее время в более крупного проекта мы обычно поставить новый класс в отдельный файл, но для наших целей здесь я могу просто написать это определение класса в этом площадке. Таким образом, мы описали данные и поведение, что этот класс будет предоставляются, начиная со свойствами и методами. Ну, это не может быть проще, основной Swift свойство просто переменная или константа, который определяется внутри класса. Там нет никакой собственности ключевое слово необходимо в Свифт. Нам не нужно, чтобы написать добытчиками или сеттеры здесь. Если вы пишете переменную внутри класса, это переменная собственности.

Вы пишете постоянна внутри класса, это постоянная собственность. Теперь еще один комментарий для Objective-C людей, остальные можно игнорировать следующее предложение. Мы не должны беспокоиться о переменных экземпляра, и синтезаторов и бэк-магазинах, это все заботятся. Он просто работает, аллилуйя. Ладно, синтаксис здесь аналогична созданию переменные и константы вне класса, применяются те же правила. Если Swift не можем вывести тип данных от некоторого начального значения мы должны предоставить тип данных.Тип аннотации здесь это имя строки и заработать очки Int.

Если вы обеспечить начальное значение здесь, тем будет использоваться, когда объект этого класса экземпляра. Теперь вы можете быть, заметив, что есть ошибка выскакивать здесь. Мы будем говорить о том, что всего за секунду. См для тех из вас, кто может быть интересно, я хочу, чтобы подтвердить, что да они рассматриваются как свойства уровня экземпляра, то есть, если я создаю экземпляр 100 различных объектов этого класса одного игрока, они имеют свои собственные независимую копию имени и оценка , И да, мы можем создать класс-уровня или то, что называется свойства на уровне типа, часть данных общих для всех экземпляров, но не торопитесь мы вернемся к этому, основам первой.

Ну вот просто данные, теперь, чтобы добавить некоторые простые поведения мы добавим методы. И, как свойство только переменная или константа, который определяется внутри класса, метод функция, которая относится к классу. Мы используем те же Func ключевое слово мы использовали все вместе и все те же правила применяются. В этом случае, я создаю метод, называемый описание. Она возвращает строку, и это не принимает никаких параметров. Но я уже получаю предупреждение здесь, я буду нажмите на эту кнопку, этот класс "Игрок" не имеет инициализаторами.

Это не позволит мне экземпляр этого класса так, что это такое. См Swift, как всегда, одержим все ваши ценности всегда иметь действительный государство и сейчас нет значения имени и за счет. Так что мне пришлось этот потенциал, что я могу создать экземпляр этого класса и значения в какое-то неопределенное, нечеткой государства и что просто не допускаются в Свифт. Поэтому мне нужно либо предоставить некоторые значения по умолчанию в явном виде от этих переменных, или мне нужно, чтобы обеспечить то, что называется инициализации для этого класса, специальный метод, чтобы убедиться, что, когда он экземпляр будет немедленно существовать в допустимом состоянии и все переменные иметь значимые ценности.

Теперь я мог также отмечают эти переменные здесь в качестве дополнительного, но это не то, что я хотел бы в этой ситуации. Так давайте выберем первый вариант, просто установив некоторые значения по умолчанию этих переменных. Я могу сделать это сам, просто добавив знак равенства и давая ему какое-то значение, но если я замечаю, что здесь ошибка имеет несколько предложений для устранения проблем, чтобы исправить имя без начального значения. Так что, если мы выбираем имя, я щелкаю его, это будет установить его равным пустой строке, что очень неинтересный, но это технически начальное значение.

И у нас еще есть один для очков, так что я буду исправить, что один, а также. Теперь я мог изменить это быть какой-то более слегка значимая ценность, поэтому я буду изменить, что бы значение по умолчанию John Doe. Все права ошибке исчезает, теперь я могу создать экземпляр этого класса. Так за пределами определения класса, следующего за закрывающей фигурной скобкой я собираюсь определить новую переменную, которую я буду называть Джейк и я собираюсь хотим, чтобы это экземпляр класса игрока. Что я здесь делаю, я просто использовать слово игрока, имя нашего имени класса, а затем открывая и закрывая скобки.

Это будет создавать новый экземпляр объекта класса игрока. В Свифт мы не должны ключевое слово как новый, мы не должны Alloc, мы не должны Init, это он. Теперь у нас есть новый объект класса игрока. Я могу даже увидеть подсказку здесь, что у нас есть этот объект. Я могу Quicklook его, я вижу, что есть две части к нему. Там Джон Доу имя и оценка равна нулю. Теперь я мог бы использовать аннотацию типа, если я хотел быть четко указано, что мой переменной Джейк тип игрока, но, как и все остальное в Swift, если это так очевидно из этого первоначального значения, что создает объект игрока, я просто не нужно, тип выводится.

И то, что я сейчас могу сделать, это использовать синтаксис с точкой доступа к обоим свойства и методы этого объекта. Так jake.name = "Джейк", jake.score = 1000, Println jake.description, и мы начинаем видеть всю информацию, что мы могли бы ожидать выскакивают здесь, в панели результатов. Так определение, экземпляра и с помощью простого класса в Swift примерно так же прост и понятен, как он получает на любом объектно-ориентированный язык программирования. Итак, давайте это немного дальше и начать с добавления некоторых инициализаторов.

Adding initializers to a class

- While we can provide initial values for every single one of our properties, an alternative is to add an initializer to your class. A way of providing custom functionality that will automatically be called when a new instance is created. So, I'm beginning here with a basic class definition. I'm going to removed the initial values for both of these properties this string and the integer. As soon as I do this, I'm going to see an arrow pop-up. I can not right now instantiate objects of this class, because they might exist in an invalid state.

That's okay, I'm going to add the initializer now. So, it's just init and a code block and the empty parenthesize. This is the default initializer. It takes no perimeters, and Swift initializes do not return anything, so we don't see the return arrow here. It's like a method just called init, but we also don't need the funk keyword in front of it. It is a reserved keyword. This is understood by Swift. So, I'm going to use this to set a couple of default valleys for my two properties. So, name equal to John Doe, and score is equal to zero.

Now the arrow goes away. It is understood that this class is valid. I can instantiate this. When we do this, the init method is going to be called automatically. So, if I show the contents of this, we will see that in description. It's got that internal state. Player John Doe has a score of zero. So, moving on. If I wanted different values, if I didn't want to just accept these defaults, well, I could create the object like this, and then change its properties. If I want the option to create and initialize a new player object with different data from this default, well, I could make a custom initializer.

An initializer that accepts perimeters. So, I'll go ahead and do that an initializer with perimeters. We're still using init, except this time instead of empty parenthesis, I'm going to say name colon string. Now, we run into a problem, and that name is also a property of this class. So, if I'm wanting to accept this perimeter in and use it to set the property, well, I can't really just write name equals name. We've got kind of an issue there. I have to be explicit about this. So to avoid collisions, I could either change the perimeter name, but a better way is just that I'll do this. Self.name.

Use the (forward) self meaning the current instance of this class. To make it very clear, when I'm referring to a property of this class self.name as opposed to just a perimeter being past in. Other languages use this or me to refer to the same idea the current instance of this class. Swift uses self. It's true we don't always need to use self. I didn't have to use it here for the score property, but it is good practice for clarity, if there's any possibility for misunderstanding as to what you're referring to.

All right, so we now have two initializers. If I leave the original init method in this class, I now have a choice of either instantiating an object using the empty parenthesis like this, or instantiating by passing in a value with this new initializer. So, just creating a couple of new lines of code, using the custom initializer will create second player equal to player name:Alice. Then, I'll print out Alice's description. So, we can use the version with the empty parenthesis, which will set it to John Doe, or we can use the version passing in some information.

Now notice that I do need to provide a named perimeter here. If I had attempted to leave that out and just pass in a string literal value, I'm going to see the little arrow pop-up here. Although it's pretty obvious what this is, so it should suggest a fix it. Yes, the missing argument label name, so fix it just insert name, and it'll fix it for us. So, two separate object each with its own set of data, but created using different initializers. Now just as initializers are automatically called when an object is instantiated, we also have the option to create a de initializer, that is automatically called when an object reaches the end of its lifetime.

This is just a word de init with a code block. Now, you can only have one de initializer, and it isn't customizable. This takes no perimeters. It doesn't have any parenthesis. It returns no values, but this is where you would put any necessary cleanup code an object needs to do. Now in general, while initializes are very common, you do not need de initializers for the majority of your classes. It's only needed in situations like having a class that opens a connection to a database or file when it's first instantiated.

It keeps that connection open through the lifetime of the object, and you need to make sure that object has closed the connection to that resource before it's de-allocated. Most of the time, you do not need a de init. Now, calling de init is not under your direct control. You don't actually do it yourself. In Swift, we don't do manual memory management. Swift uses something called automatic reference counting or ARC. While we do manually create our objects when we decide to instantiate them here, whether it's using a normal init method or an overloaded one, we are deciding to create that object.

We say whether instantiated, but Swift keeps track of when these objects are no longer needed. It will decide when to de allocate them, and at that point is when the de init would be called. Now bear in mind, if you have a class that does hold open a resource, there's nothing to stop you writing your own method that preforms any necessary cleanup. Just calling it yourself within the normal logic of your programming, that is what you typically should be doing. You don't need to leave it to de init, but you can use de init to ensure that cleanup has happened.

Adding initializers to a class Добавление инициализаторами к классу

- Пока мы можем предоставить начальные значения для каждого из наших свойств, альтернатива, чтобы добавить инициализатор для вашего класса.Способ обеспечения функциональности, которая будет автоматически вызываться при создается новый экземпляр. Так, я начинаю здесь с основного определения класса. Я собираюсь удалены начальные значения для обоих этих свойств этой строки и целое число. Как только я это сделаю, я буду видеть стрелку всплывающее окно. Я не могу сейчас создавать объекты этого класса, потому что они могут существовать в недопустимом состоянии.

Это нормально, я собираюсь добавить инициализатор сейчас. Таким образом, это просто инициализации и блок кода и пустой скобки. Это инициализации по умолчанию. Эта команда не имеет периметр, и Свифт инициализирует ничего не вернуть, поэтому мы не видим возвращение стрелка здесь. Это как метод просто вызывает инициализации, но мы также не должны ключевое слово фанк перед ним. Это зарезервированное слово. Это понимают Свифт. Итак, я собираюсь использовать это, чтобы установить пару долинах умолчанию для моих двух свойств. Таким образом, название равна John Doe, и оценка равна нулю.

Теперь стрелка уходит. Понятно, что этот класс является действительным. Я могу создать экземпляр этого. Когда мы делаем это, метод инициализации будет вызван автоматически. Так что, если я показать содержимое этого мы видим, что в описании. Он получил, что внутреннее состояние. Игрок John Doe имеет нулевую оценку. Итак, двигаемся дальше. Если бы я хотел разные значения, если я не хочу, чтобы просто принять эти значения по умолчанию, ну, я мог бы создать объект, как это, и затем изменить его свойства. Если я хочу опцию, чтобы создать и инициализировать новый объект плеер с разным данным от этого умолчанию, хорошо, я мог бы сделать собственную инициализатор.

Инициализатор, который принимает периметров. Таким образом, я буду идти вперед и делать то, инициализатором с периметров. Мы по-прежнему с помощью Init, но на этот раз вместо пустого скобках, что я собираюсь сказать, имя толстой кишки строку. Теперь мы столкнулись с проблемой, и это имя также свойство этого класса. Так что, если я хотел принять этот периметр и использовать его для установки свойства, ну, я не могу просто написать имя равна имя. У нас есть своего рода вопрос там. Я должен быть четко об этом. Поэтому, чтобы избежать столкновения, я мог бы либо изменить имя по периметру, но лучший способ это просто, что я сделаю это. Self.name.

Используйте (вперед) себя есть текущий экземпляр этого класса. Чтобы сделать это очень ясно, когда я имею в виду свойство этого класса self.name, а не просто дойдя в периметр. Другие языки используют ту или сослаться на той же идее текущий экземпляр этого класса. Swift использует себя. Это правда, что мы не всегда нужно использовать себя. Я не должен был использовать его здесь оценка имущества, но это хорошая практика для ясности, если есть какая-то возможность непонимания того, что Вы имеете в виду.

Ладно, теперь у нас есть два инициализаторами. Если я оставлю оригинальный метод инициализации в этом классе, у меня теперь есть выбор: либо экземпляра объекта с помощью пустой скобки, как это, или экземпляра, передавая значение с этой новой инициализаторе. Так, только создав несколько новых строк кода, используя пользовательский инициализатор создаст второй игрок, равный Имя игрока: Алиса. Тогда я буду распечатать описание Алисы. Таким образом, мы можем использовать версию с пустой скобках, в котором будут определены его Джон Доу, или мы можем использовать версию, проходящий в каком-то информации.

Теперь обратите внимание, что мне нужно, чтобы обеспечить по имени периметр здесь. Если бы я попытался оставить это, и просто передать в буквальном значении строки, я иду, чтобы увидеть маленькую стрелку всплывающее здесь. Хотя это довольно очевидно, что это такое, поэтому он должен предложить исправить ее. Да, отсутствует имя аргумент метка, так это исправить просто вставить имя, и оно будет исправить это для нас. Таким образом, два отдельных объекта каждый со своим собственным набором данных, но созданные с использованием разных инициализаторов. Теперь же, как инициализация автоматически вызывается, когда экземпляр объекта, мы также имеем возможность создать де инициализатор, который автоматически вызывается, когда объект достигает конца своей жизни.

Это просто слово-де-инициализации с блоком кода. Теперь вы можете иметь только один де инициализатор, и это не настраивается. Это занимает не периметров. Это не имеет никакого скобки. Это не возвращает значения, но это, где бы вы поставить любую необходимую код очистки объект должен делать. В настоящее время в целом, в то время как инициализирует очень распространены, вам не нужно-де-инициализаторами для большинства ваших классов. Это необходимо только в ситуациях, подобных иметь класс, который открывает подключение к базе данных или в файле, когда он первый экземпляр.

Он держит его открытым в течение жизни объекта, и вы должны убедиться, что объект закрыл соединение к ресурсу, прежде чем он де-выделены. Большую часть времени, вам не нужно де инициализации. Теперь, позвонив де Init не находится под вашим непосредственным контролем. Вы на самом деле не сделать это самостоятельно. В Свифт, мы не будем делать ручное управление памятью. Swift использует то, что называется автоматическая подсчет ссылок или дуги. В то время как мы вручную создаем наши объекты, когда мы решаем их экземпляры здесь, будь то с помощью обычной инициализации метод или перегруженный один, мы решаем чтобы создать этот объект.

Мы говорим ли экземпляр, но Свифт отслеживает, когда эти объекты не больше не нужны. Он будет решать, когда де выделить их, и в этот момент, когда де инициализации будет называться. Теперь, имейте в виду, что если у вас есть класс, который проведут открытую ресурс, нет ничего, чтобы остановить вас писать свой собственный метод, который преформ любую необходимую очистку. Просто назвав его себе в нормальной логики вашего программирования, то есть то, что вы обычно должны делать. Вам не нужно оставить его де Init, но вы можете использовать де инициализации, чтобы гарантировать, что очистка произошло.

Using inheritance

- On to inheritance. A key point of object orientation is to reuse and extend code between classes. So when creating a new class in Swyft we can inherit from an existing one by writing the colon after our new class name followed by the class we want to inherit. Now with inheritance relationships some languages use terms like base class, and derived class, or even parent and child class. In Swyft, as in many languages, we say super class and sub class. So this is my new class here, PremierPlayer.

We are inheriting from Player. It is the super class, our new class is the sub class. We can still think of the colon as meaning is of type, so PremierPlayer is a type of Player. Now just by doing this we would get all the properties and methods of the super class. So right now without adding anything to this class definition I can go ahead and instantiate new objects of this class type. So newPlayer is a PremierPlayer. I can use the initializer that it has. I immediately have access to the description method, I have access to the name property, and the score property.

But really there's no point inheriting if I'm not going to change and extend in some way. So I can add a new method to the new class. Going to add one called calculateBonus. This won't return anything, but it will change the score and add a thousand to it and then print out a message about the new score. Now what we'll find is that will be immediately available on instances of the new PremierPlayer class. We will have the calculateBonus method, but down here where I'm just creating a normal Player we will not have access to that method.

We just won't find it. But what else? Well we can also go ahead and add new properties to this class. However, we're going to run into one issue immediately. So I'll add a new variable called memberLevel and it's a type of string. I'm immediately going to see this error pop up because the problem is when I add a new property, a new piece of data to the sub class and this doesn't have a default value and I haven't given this a default value, then the initializer that we've been using here creating a new PremierPlayer just passing in a name, that initializer was defined in the super class.

This is that one here, passes in the string, sets that to the name property, and sets the score property. The issue is by adding extra data, well that initializer isn't good enough anymore because it's only initializing the properties defined in the super class, it's not going to initialize our extra data. Now I have a couple of choices here. One is I could provide a default value on the variable itself in our new class. That would make the error go away. The other option is to provide our own initializer in this new class, but there's now a couple of extra steps for that because we're in an inheritance relationship.

So inside the new class I'm going to go ahead and add an init, and as soon as I do that we're going to get another error because init exists in both the super class and the sub class now and there's potential for misunderstanding. Now if I click the error, Xcode is going to suggest a fix that we need to add the override keyword, and this is the way that we do this in Swyft. We must explicitly say when we want to replace the automatically inherited behavior from the super class with our own more specialized behavior in the sub class.

Now this is another safety feature of Swyft. We must be explicit with this override keyword whenever we're replacing behavior from the super class. The compiler will check this. It will prompt me to add the override keyword if I missed it, and it won't let me add the override keyword if what I'm trying to override doesn't actually exist in the super class. So now inside this overridden initializer I'm going to add a line to give my additional property a new value. So set memberLevel property to Gold.

But we still have an error. Just to add some clarity here I'm going to comment out a couple of lines below so we can get things sorted out here. I see the error on override init. It's telling me that Super.init isn't called before returning from initializer. This error is turning up because we don't really want to completely replace the initializer in the super class, we want to add to it. So we're being prompted to make sure that we provide our own additional behavior in our new overridden initializer, and then we can go and tell Swyft to go and do the original behavior in the super class anyway.

We do this by adding super.init. We're calling from our PremierPlayer class into our super class which is Player and calling in this case the default initializer. This idea is not just true for initializers, it's true for any method. If, for example, inside my new class I wanted to extend the behavior of the existing description method that was in my super class, this is the one here that says Player has a score of whatever the score is, well I can do that fairly easily.

In my new class I can start typing the name and it can show me that there is a description method that returns a string. If I just hit return what it's going to do is give me the entire signature for overriding this properly, so it's override func description. Now unlike with an initializer, when I'm overriding a normal method I can completely replace the behavior in the super class. I don't have to make a call to super dot anything, although it is often useful. So let's say I just want a slightly more detailed message in this new specialized sub class.

So I'm going to make a call to the description method that's already defined in the player class, and I'll get that. So let the original method is whatever comes back from calling super.description. Then I'm going to just use a little bit of string interpolation to create a longer message. So to return the original message and is a whatever, gold level, silver level, member. That should be completely fine for this description option here. Now let's go ahead and test this and to make sure we're getting a new Player object being created.

One of the issues here is because in my new class I've overridden the initializer, but I've only provided one with the empty parentheses here, it's now complaining that I can't initialize with this extra piece of information because it's not inheriting that extra initializer now. That's okay. The way that I want this to work I can just delete that. We can create a PremierPlayer with our new initializer, and then to test the fact that it works we'll write out newPlayer.description.

Here what I would expect to see is the overridden version of that, which includes the behavior in the top one, so Player John Doe has a score of 0 and is a Gold member as opposed to calling it with the normal class below here, which would just say Player John Doe has a score of 0. So this is the basics of overriding. Now if I did one to prevent behavior in a super class, say I've got this method and I think this description method is really good and I want to make sure that nobody overrides it in a sub class, I can do that by adding the keyword final in front of it.

This is now going to cause an error below. It's going to tell me instance method is trying to override one that's defined as final, you can't override that. Well that's fine, I'm going to remove that. You can even mark an entire class as final. I could actually mark this as final class player and it would stop this inheritance attempt from happening at all. It's not necessary to happen all the time, but it's good to know that you can do that if you need to prevent it. One last thing, unlike many other languages, including Objective-C, in Swyft classes do not inherit from a default universal base class.

So if you write a class like this Player class here without a colon after it, this is regarded as a base class in itself and it does not secretly inherit from something else behind the scenes.

Using inheritance Использование наследования

- На наследования.Ключевым моментом объектно-ориентированного является повторное использование и расширить код между классами. Так при создании нового класса в Swyft мы можем наследовать от существующего в письменной форме толстой кишки после нашего нового имени класса с последующим класса мы хотим, чтобы наследовать. Теперь с отношениями наследования некоторые языки используют такие термины, как базовый класс, и производного класса, или даже родителей и дочернего класса. В Swyft, как и во многих языках, мы говорим, супер класс и суб-класс. Так что это мой новый класс здесь, PremierPlayer.

Мы в наследство от игрока. Это супер класс, наш новый класс класс к югу. Мы все еще можем думать о толстой кишке смысл типа, так PremierPlayer является тип игрока. Теперь просто делать это мы хотели бы получить все свойства и методы суперкласса. Так что сейчас, ничего не добавляя к этому определению класса я могу идти вперед и экземпляр новые объекты этого типа класса. Так newPlayer является PremierPlayer. Я могу использовать инициализатор, что она имеет. Я сразу же иметь доступ к методу описания, у меня есть доступ к имени имущества, а также оценка недвижимости.

Но на самом деле нет никакого смысла наследовать, если я не собираюсь изменять и расширять в некотором роде. Так что я могу добавить новый метод к новому классу. Добавим один называется calculateBonus. Это ничего не вернется, но это будет изменить счет и добавить тысяч до него, а затем распечатать сообщение о новом счете. Теперь то, что мы найдем то, что сразу же станет доступным для экземпляров нового класса PremierPlayer. Мы будем иметь метод calculateBonus, но здесь, где я просто создание нормальный игрок не будет иметь доступ к этому методу.

Мы просто не найдете. Но что еще? Ну мы также можем пойти дальше и добавить новые свойства этого класса. Тем не менее, мы собираемся выполнить немедленно в одном вопросе. Так что я буду добавлять новую переменную с именем memberLevel и это тип строки. Я сразу же увидите эта ошибка выскочит, потому что проблема, когда я добавить новое свойство, новый кусок данных к классу югу, и это не имеет значения по умолчанию, и я не дали его значение по умолчанию , то инициализатор, что мы использовали здесь создание нового PremierPlayer просто проходил в имени, что инициализатор был определен в родительском классе.

Это то, что один здесь, проходит в строке, устанавливает, что имя свойства, и устанавливает оценка имущества.Вопрос, добавив дополнительные данные, хорошо, что Инициализатор не достаточно хорош больше, потому что это только инициализации свойства, определенные в родительском классе, она не собирается инициализировать наши дополнительные данные. Теперь у меня есть несколько вариантов здесь. Одним из них является Я мог бы привести значение по умолчанию, на самой переменной в нашем новом классе. Это сделало бы ошибка исчезнет.Другой вариант заключается в предоставлении нашу собственную инициализатору в этом новом классе, но теперь несколько дополнительных шагов для этого, потому что мы находимся в отношениях наследования.

Так внутри нового класса я собираюсь идти вперед и добавить инициализации и как только я это сделать, мы собираемся, чтобы получить другую ошибку, потому что инициализации существует и в супер класса и подклассов сейчас и есть потенциал для непонимания , Теперь, если я нажму ошибку, Xcode собирается предложить исправить, что мы должны добавить ключевое слово переопределения, и это путь, который мы будем делать это Swyft. Мы должны явно сказать, когда мы хотим заменить автоматически наследуются поведение от суперкласса с нашей собственной более специализированное поведение в классе югу.

Теперь это еще один безопасность особенностью Swyft. Мы должны быть ясными с этим коррекции ключевое слово всякий раз, когда мы заменяем поведение от суперкласса.Компилятор будет проверять этот. Вам будет предложено мне, чтобы добавить ключевое слово переопределения, если я пропустил его, и он не позволит мне добавить ключевое слово переопределения, если то, что я пытаюсь переопределить на самом деле не существует в родительском классе. Так что теперь внутри этой перегруженной инициализаторе я собираюсь добавить строку, чтобы дать моему дополнительное свойство новое значение. Так установлено memberLevel свойство золота.

Но у нас еще есть ошибки. Просто добавить некоторую ясность здесь я иду закомментировать несколько строк ниже, чтобы мы могли получить вещи отсортированные здесь. Я вижу ошибку на коррекции инициализации. Это говорит мне, что Super.init не называется до возвращения из инициализаторе. Эта ошибка поворачивает вверх, потому что мы действительно не хочу, чтобы полностью заменить инициализатору в супер класс, мы хотим добавить к нему. Таким образом, мы время предложено, чтобы убедиться, что мы предоставляем нашу собственную дополнительное поведение в нашем новом переопределенном инициализаторе, и тогда мы сможем пойти и сказать Swyft пойти и сделать оригинальный поведение в супер класс в любом случае.

Мы делаем это путем добавления super.init. Мы совершаете звонок из нашего класса PremierPlayer в нашей супер класс, который плеер и призывая в этом случае инициализатор по умолчанию. Эта идея не только верно для инициализаторах, это верно для любого метода. Если, например, в моем новом классе я хотел расширить поведение существующего метода описания, что было в моей супер-классом, это один здесь, что говорит игрока есть счет в любой счет, ну что я могу сделать, что довольно легко.

В моем новом классе я могу начать вводить имя и он может показать мне, что есть описание метод, который возвращает строку. Если я просто нажмите вернуть то, что он собирается сделать, это дать мне всю подпись для переопределения это правильно, так что коррекция Описание FUNC. Теперь в отличие от инициализатором, когда я перекрывая нормальный метод, который я может полностью заменить поведение в родительском классе. Я не должен сделать вызов супер точка-либо, хотя часто бывает полезно. Так что давайте говорить, что я просто хочу немного более подробное сообщение в этой новой специализированного класса к югу.

Так что я собираюсь сделать вызов метода описания, что уже определено в классе игроков, и я получу это. Итак, давайте оригинальный метод все возвращается из вызова super.description. Тогда я буду просто использовать немного интерполяции строк, чтобы создать более длинное сообщение. Таким образом, чтобы вернуть исходное сообщение и все, золотой уровень, серебро уровень, член. Это должно быть полностью нормально для этого описания опции здесь. Теперь давайте идти вперед и проверить это и, чтобы убедиться, мы получаем новый объект игрока создается.

Один из вопросов, здесь, потому что в моей нового класса я переопределить инициализатор, но я только предоставил один с пустыми скобками здесь, то теперь жалуются, что я не могу инициализировать эту дополнительную часть информации, потому что это не наследование что дополнительный инициализации сейчас. Это нормально.Так, что я хочу, чтобы это работало, я могу просто удалить это. Мы можем создать PremierPlayer с нашей новой инициализаторе, а затем проверить тот факт, что он работает, мы напишем из newPlayer.description.

Вот то, что я ожидал увидеть это перегруженной версии из той, которая включает в себя поведение в верхний, так игрока John Doe имеет оценку 0 и Золотой участник в отличие от вызова его с обычным классом ниже, на которых просто сказать игрока John Doe имеет оценку 0. Таким образом, это является основной переопределения. Теперь, если я сделал один, чтобы предотвратить поведение в супер класса, сказать, что я получил этот метод, и я думаю, этот метод описание очень хорошо, и я хочу, чтобы убедиться, что никто не отменяет его в классе югу, я могу сделать это, добавивокончательный ключевым словам перед ним.

Это теперь будет вызывать ошибку ниже. Это будет сказать мне метод экземпляра пытается переопределить один, который определен как окончательный, вы не можете изменить это. Ну это нормально, я иду, чтобы удалить это. Вы даже можете пометить весь класс как финал. Я мог бы на самом деле отметить это как окончательное классный игрок, и было бы остановить эту попытку наследство от вообще происходит. Это не обязательно, чтобы это произошло все время, но это хорошо, чтобы знать, что вы можете сделать, если вам нужно, чтобы предотвратить его. Одна последняя вещь, в отличие от многих других языках, в том числе Objective-C, в классах Swyft не наследуют из универсального базового класса по умолчанию.

Так что, если вы пишете класс как этого класса плеер тут без двоеточия после него, рассматривается в качестве базового класса в себе и это не тайно наследуют от чего-то еще за кулисами.

Creating computed properties

- The kinds of properties we've seen so far just defining variables or constants inside a class do have a more specific name, these aren't just properties they are known formally in Swift as stored properties, that means that they're responsible for storing their own values, containing this data inside each instance of this class. Now that probably seems fairly typical and it is, stored properties are normal but there are other options. We can also create a computed property and that's a property that will calculate a value rather then internally store one.

So here's an example, I have a simple class called Person that contains two normal stored properties, firstName and lastName, both strings, I'm going to add a new computed property, fullName, a convenient way for someone to ask for the full name of the Person object. Now this is going to be typed as a string, but I don't want to duplicate this data, I don't want to store another copy of that information, I just want it to feel like it's an internal property, but actually calculate and return that data. Now right now this looks like a normal variable, but that's because we're not finished.

For a computed property, we then add a code block, just the opening and closing curly braces. And inside that we can add a code block for a getter, just the word get and another code block and this is where we will return the computed property, we'll calculate what it should be and send it back. We have to send back a string, because we have typed this as a string. Now optionally what you can also do is add another code block for a setter, to set the value it is very common that computed properties only have a getter and that would otherwise be known as a read only computer property, to do that I would just delete the set block.

And my getter for this example would be pretty simple, all I want to do is return a string that is firstName then a space and then lastName, I'm using concatenation here with the plus sign, though I could have also used string interpolation. Let's go ahead and prove that this works, down bellow I am instantiating a new object from the Person class, I am setting some basic data. So then I just want to go ahead and refer to that fullName property, so do a print line of examplePerson.fullName and we can see over here in the results pane that it's spitting out that as one string.

Now at the moment up here I do have a set block without any code in it, I'm just going to remove this to prove a point that with only a getter inside there if I do go ahead and try and set this value, so accessing it like it's a property, but just saying examplePerson.fullName = some new value I'm going to expect this to detect an issue here that we cannot assign to fullName, it is a read only computed property. Now if I really wanted to have a setter, so I'm gonna come back into the computer property block and add that set block back in again.

What I'd have to understand is what I'd be getting, I'd be getting a single string value passed in and I would need to write a little code to split this apart and put it in the firstName and lastName stored properties of this class because the computed property itself doesn't store any information. So when you add this set block, what you implicitly get inside is a new value called appropriately enough newValue. So I could add code here to split this newValue data into two separate pieces that would actually split it into an array and I could set firstName, the stored property to the first part of the array and LastName stored property to the second part of the array.

Now I'm not doing any error checking here so this is quite brittle code, this would be prone to breaking if somebody started to send in say three names inside this piece, or just one. But this would be the general approach, having said that most likely for this example we would make this a read only property and only have a getter, but at least you can see down here that it seems to be working, that we're not actually getting that error anymore because it's understood we do have a set block in our property. So this is what I'm going to do, I'm going to remove that entire set block and go back to the get.

This is going to make the error appear again, so I'll just go ahead and get rid of that, because in fact with computed properties it is so common to only have a get block that when that is the case, you can just omit it, you can get rid of the get block entirely and make it so the opening and closing curly braces of the get block is gone so the only thing that we have for our computed property is a return statement inside the main set of curly braces, now this is understood by Swift as a read only computed property and this is the simplest way to write one.

Using inheritance Создание вычисляемых свойств

- Виды недвижимости, которые мы видели до сих пор только определения переменных или констант внутри класса действительно имеют более конкретное имя, это не просто свойства, они, как известно, официально у Свифта, как хранимые свойств, это означает, что они отвечают за хранения свои собственные ценности, содержащие эти данные внутри каждого экземпляра этого класса. Теперь, вероятно, кажется довольно типичны, и это, хранящиеся свойства нормально, но есть и другие варианты. Мы также можем создать вычисляемый недвижимость, и это имущество, которое будет вычислять значение, а затем внутри хранить один.

Так вот меня, например, просто класс, называемый Person, который содержит два нормальных свойств хранимых, ИМЯ и ФАМИЛИЯ, обе строки, я иду, чтобы добавить новый компьютерной имущество, FULLNAME, удобный способ для кого-то спросить по полному имени объекта Person. Теперь это будет набран в виде строки, но я не хочу, чтобы дублировать эти данные, я не хочу, чтобы сохранить еще одну копию этой информации, я просто хочу, чтобы чувствовать себя, как будто это внутреннее свойство, но на самом деле вычислить и возвращает эту информацию. Теперь прямо сейчас это выглядит как обычной переменной, но это потому, что мы не закончили.

Для компьютерной собственности, мы затем добавить блок кода, только открытие и закрытие фигурные скобки. И внутри, что мы можем добавить блок кода для добытчика, просто слово получит и другой блок кода, и это то, где мы вернем компьютерной собственность, мы посчитаем, что это должно быть, и отправить его обратно. Мы должны отправить обратно строку, потому что мы ввели это как строку. Теперь, возможно, что вы также можете сделать, это добавить еще один блок кода для сеттера, чтобы установить значение это очень распространено, что вычисленные свойства есть только добытчика и что в противном случае будет известен как только для чтения компьютерной имущества, для этого я бы просто удалить установленном блоке.

И мой добытчик для этого примера было бы довольно просто, все, что я хочу сделать, это вернуть строку, которая Имя то пространство, а затем фамилия, я использую конкатенацию здесь со знаком плюс, хотя я мог бы также использоваться интерполяции строк. Давайте пойдем дальше и доказать, что это работает, вниз ниже я экземпляра нового объекта из класса Person, я ставлю некоторые основные данные. Тогда я просто хочу, чтобы идти вперед и обратиться к этому FULLNAME собственности, так делать печатать строку examplePerson.fullName, и мы видим здесь, в панели результатов, что он плевал на то, что, как одну строку.

Теперь в настоящее время здесь у меня есть набор блока без какого-либо кода в нем, я просто хочу, чтобы удалить это доказать свою точку зрения, что только добытчика внутри там, если я идти вперед и попробовать и установить это значение, так доступа к ней, как будто это свойство, но просто говорю examplePerson.fullName = некоторое новое значение, что я собираюсь ожидать, что это обнаружить проблему здесь, что мы не можем назначить FULLNAME, это только для чтения вычисляется собственности. Теперь, если я действительно хотел, чтобы установщик, так что я собираюсь вернуться в блоке компьютера имущества и добавить, что набор блок снова.

То, что я должен был бы понять, что я бы получить, я бы получать одно значение Строка, передаваемая в и я должен был бы написать немного кода, чтобы разделить это друг от друга и положить его в Имя и фамилия хранящихся свойств Этот класс потому, что сама компьютерная свойство не хранить любую информацию. Поэтому, когда вы добавляете этот комплект блок, то, что вы неявно получить внутри новое значение называется соответственно достаточно новое_значение. Так что я мог добавить код здесь, чтобы разделить этот NEWVALUE данные в двух отдельных частей, которые на самом деле разбить его на массив, и я мог установить Имя, сохраненного свойства в первой части массива и фамилия хранится имущество на второй части массива ,

Теперь я не делаю какой-либо проверки здесь ошибка, так что это вполне ломкими код, это будет ломкими, если кто-то начал посылать, скажем, три названия внутри этой части, или только один. Но это было бы общий подход, сказав, что, скорее всего, для данного примера мы хотели бы сделать это свойства только для чтения и только поглотитель, но по крайней мере вы можете увидеть здесь, что это, кажется, работает, что мы не на самом деле получить эту ошибку больше, потому что понимали, у нас есть множество блок в нашей собственности. Так это то, что я собираюсь делать, я иду, чтобы удалить весь этот набор блок и вернуться в ГЭТ.

Это собирается сделать ошибка появится снова, так что я буду просто идти вперед и избавиться от этого, потому что на самом деле с вычисленным свойствам он так часто только есть получить блок, который, когда это так, то вы можете просто опустить это, вы можете избавиться от GET блока целиком и сделать это так, открытие и закрытие фигурных скобок Получить блока зашли так единственное, что мы имеем для нашей компьютерной собственности оператор возврата в главный фигурные скобки, теперь это понятно Свифт, как только для чтения компьютерной имущества, и это простой способ, чтобы написать одну.

Using type properties and methods

- The properties and methods we've created so far are instance-level properties and methods meaning that every object we create from a class has its own independent set of data and its own independent methods that act on that data. A change to a property of one instance or a call to a method of one instance does not affect any of the others. But we can also define class level or, in Swift, what are called type properties and type methods. They belong to the type itself, to our class, not to any one instance of that class.

So here's an example. I have a simplistic BankAccount class that I have created here, a few pieces of data, constants for accountNumber and routingCode. There's a variable for balance and interestRate and a few simple methods as well as an initializer, nothing special about any of this. So I have this property here called interestRate. It's a float and I'm giving it a literal value. But let's imagine that our business rules are such that interestRate should be the same for all BankAccounts. We might have a hundred thousand instances of this class, but they should all share the same interestRate.

Whatever it is, they all share it. Well I don't want a hundred thousand separate copies of this variable, and if it changes, to have to update it a hundred thousand times. So what I can do is define this as a type property so it works on the entire class. There's only one of them, and it will exist for the entire class whether I have a hundred thousand instances or even none at all. So I make it a class level or a type property by just adding the word class right in front of var. Now, as soon as I do this I'm going to run into one issue here.

At the time I'm recording this with a late beta version, I'm going to see this message that class variables are not yet supported. Now, to me, this suggests that it is expected to be able to do this. It's just not supported in my current beta. So if there is a need for you, just check to see if you can add the keyword class in front of a regular stored property because this may not be an issue at the time you're watching this course. However, I'm not stuck. I actually can do this right now as long as it's a computed property rather than a stored property.

So I'm going to make a quick change that instead of setting this equal to 2.0, I'll just add a code block here and tell it to return 2.0. So we have a read-only computed property here, and now that error goes away. Now when you have a type property working at the class level, the difference is that we don't use the name of an instance to deal with this. We use the name of the class itself, and we work with instance-level properties, normal properties here like accountNumber, routingCode and balance.

Well, I need to have an instance of that class to work with them. So down here at the bottom I'm creating two instances of the BankAccount class, firstAccount and secondAccount. And if I use those with dot syntax, I can get access to the accountNumber property, the balance property, the routingCode property. I do not see interestRate, because it doesn't work on an instance level anymore. What I need to do is use the name of the class, BankAccount. and now I get access to interestRate.

I can see in the playground just by writing this it's returning 2.0. And the thing is this, this type property is always available, even if we have no instances at all of this class. So if I comment out these two creations of the instances here, we don't have any instances of this class but this property is still available. Now we can also do the same thing with a method. We can convert a method from working at the instance level into working at the class level by writing the word class in front of it. Now, I wouldn't do this with methods like deposit and withdraw which are intended to work on instance level data.

But if I had another method, let's say I've got a function called example that just does a print line statement here. I could convert this into a type-level or class-level method by just writing the word class ahead of func. So this is now a type method, and like the type property before it we get to it by using the name of the class. So it's BankAccount.example, not any instance name of this. One important thing is because type methods where you've used the word class in front of them, they work on the class regardless of if you have any instances of this class or not so you cannot refer to instance-level data inside of this class.

Any attempt to access normal instance-level stored properties like the balance or the accountNumber would cause a compile error inside this method. Although, you can refer to class-level data like the interestRate property that we just made because that does work at the class level. So I could say interestRate is self.interestRate. That's completely accessible at this level because this is a class-level method. Now it is true that most of your properties and methods will be instance-level.

They'll work at that level, but these do come in very useful from time to time.

Using type properties and methods Используя свойства и методы типа

- Свойства и методы, которые мы создали до сих пор, свойства и методы означает, что каждый объект мы создаем из класса имеет свой собственный независимый набор данных и собственных независимых методов, которые действуют на этих данных на уровне экземпляра.Изменение в собственности одного экземпляра или вызове к способу одном случае не влияет на других. Но мы также можем определить уровень класса или, Свифт, то, что называется свойства типа и методы типа. Они принадлежат к самой типа, к нашему классу, а не к какой-либо одной инстанции этого класса.

Так вот пример. У меня есть упрощенное класс BankAccount, что я создал здесь, несколько кусочков данных, констант для AccountNumber и routingCode. Там это переменная для баланса и InterestRate и несколько простых методов, а также инициализации, ничего особенного обо всем этом. Так что я эту недвижимость здесь называют InterestRate. Это поплавок, и я даю ей значение литерала. Но давайте представим, что наши бизнес-правила таковы, что InterestRate должны быть одинаковыми для всех BankAccounts. Мы могли бы иметь сто тысяч экземпляров этого класса, но все они должны одни и те же InterestRate.

В любом случае, все они имеют его. Ну, я не хочу сотен тысяч отдельных экземпляров этой переменной, а если она изменяется, чтобы обновить его сто тысяч раз. Так что я могу сделать, это определить это как свойство типа так она работает на весь класс. Там только один из них, и она будет существовать для всего класса, имею ли я сто тысяч экземпляров или даже вообще ни одной. Так я делаю это уровень класса или тип недвижимости, просто добавив класс слово прямо перед вар. Теперь, как только я делаю это я буду бегать в одном вопросе здесь.

В то время я записываю это с конца бета-версии, я собираюсь видите это сообщение, что переменные класса не поддерживаются. Теперь, для меня, это говорит о том, что он, как ожидается, будет в состоянии сделать это. Это просто не поддерживается в моем текущей бета-версии. Так что если есть необходимость для вас, просто проверить, если вы можете добавить класс ключевое слово перед очередной хранимой собственности, потому что это не может быть проблема в то время вы смотрите этот курс. Тем не менее, я не застрял. Я на самом деле может сделать это прямо сейчас, пока это компьютерная собственности, а не хранить имущество.

Так что я собираюсь сделать быстрый изменения, которые вместо того, чтобы это равно 2,0, я просто добавить блок кода здесь и сказать ему, чтобы вернуться 2.0. Итак, мы имеем только для чтения, вычисленный здесь недвижимость, и теперь, когда ошибка не уходит. Теперь, когда у вас есть Тип недвижимости работающий на уровне класса, разница в том, что мы не используем имя экземпляра, чтобы справиться с этим. Мы используем имя самого класса, и мы работаем со свойствами на уровне экземпляра, нормальные свойства здесь, как AccountNumber, routingCode и баланса.

Ну, мне нужно иметь экземпляр этого класса для работы с ними. Так здесь внизу я создаю два экземпляра класса BankAccount, firstAccount и secondAccount. И, если я использую те, с точечный синтаксис, я могу получить доступ к свойству AccountNumber, имущество баланса, имущества routingCode. Я не вижу InterestRate, потому что он не работает на уровне экземпляра больше. Что мне нужно сделать, это использовать имя класса, BankAccount. и теперь я получаю доступ к InterestRate.

Я вижу на детской площадке, просто пишу это это возвращение 2,0. И что это, это тип недвижимости всегда доступны, даже если мы не имеем ни одного экземпляра вовсе этого класса. Так что, если я закомментировать эти два творения случаях здесь, мы не имеем каких-либо экземпляров этого класса, но это свойство по-прежнему доступны. Теперь мы можем также сделать то же самое с методом. Мы можем преобразовать метод работать на уровне экземпляра в плане работы на уровне класса, написав класс слов перед ней. Теперь, я бы не сделать это с методами, как вносить и снимать которые предназначены для работы на данных об уровне экземпляра.

Но если бы мне пришлось еще один способ, скажем, у меня есть функция, называемая пример, который просто делает линии оператор печати здесь. Я мог бы преобразовать это в уровне типа или метода класса уровня, просто писать класс слов впереди FUNC. Так что это теперь метод типа, и, как типа собственности до него мы получаем к нему, используя имя класса. Так что это BankAccount.example, а не какой-либо имя экземпляра этого. Одна важная вещь, потому что методы типа, где вы использовали слово класса перед ними, они работают от класса независимо от того, если у вас есть какие-либо экземпляры класса или нет, так что вы не можете обратиться к данным на уровне экземпляра внутри этого класса ,

Любая попытка доступа нормальный экземпляр, которые хранятся свойства, как баланса или AccountNumber вызовет ошибку компиляции внутри этого метода. Хотя, вы можете обратиться к данным на уровне класса, что свойство InterestRate, что мы только что сделали, потому что это действительно работает на уровне класса. Так что я мог сказать, InterestRate является self.interestRate. Это полностью доступны на этом уровне, потому что это метод класса уровня. Теперь это правда, что большинство ваших свойств и методов будет на уровне экземпляра.

Они будут работать на этом уровне, но они приходят в очень полезно время от времени.

Defining lazy properties

- We have seen that Swift demands that our variables and constants are given meaningful values before they're used. And we've seen a couple of ways to ensure that this happens in our classes. Either with initializers or by providing values in the property declaration like I'm doing here. Sometimes, calculating these initial values as soon as an object is instantiated is not the best use of our applications time. Imagine in our class that we have a property called bonus. And sometimes we'll use this property and sometimes we won't. The problem is here, that the bonus isn't given a literal value it's going to get it's value from another function called getDailyBonus in my example here, that we can assume needs to do some complex processing to figure it out.

Okay, it's really just generating a random number but let's imagine this needs to go out over to the web or get a value from some non-trivial calculation. The thing is, when I instantiate this class what's going to happen is that Swift will go ahead and initialize all these instance level properties and that will cause that function to be called I can even see the results of that in the playground here. I can see that this new object that's been created does have that data inside it. I really don't need to call this function unless I need to access this property.

One way, is I could make it optional using the question mark I could define bonus as an optional int. Then start adding some logic to it so that when I need to access this property will check it for being nil and if it is nil then we'll go fetch that value. But another way, an easier way is that in Swift we can make it a lazy property. With a lazy property we describe the initial value the same way we would normally, but Swift won't bother actually initializing the property until someone attempts to access it.

And it's incredibly easy, all I do is add the word lazy before our var declaration. Now notice the immediate difference without the word lazy. When I'm instantiating the object I can see the results here that this function is being called, it outputs this print line at the top it generates this random number. But if I put that word lazy back in front of it the call to the function disappears it isn't happening right now. The object is describing itself as having a name of John Doe, a score of zero and the bonus is currently nil.

But unlike an optional, I don't have to worry about this bonus being nil, I don't have to check it for being nil, I don't have to unwrap it. Because as soon as I attempt to access a lazy property, I'm just going to do that, as soon as this is instantiated I'm going to go ahead and print out whatever newPlayer.bonus is that is going to cause Swift to immediately initialize it it will call the function, it will get a value and it will return it as if this had a value all along. It will always have a value if I try to use it.

One last thing to point out, lazy properties are always variables. It's always lazy var, it's a compile error if you try and say lazy let. That's because under the hood, the state of this piece of data is actually changing it can begin as nil and then later be given a value. That would not be allowed with a constant which must be given a set value as soon as an object is initialized.

Defining lazy properties Определение ленивых свойства

- Мы видели, что быстрые требования, что наши переменные и константы, приведенные осмысленные значения, прежде чем они привыкли. И мы видели несколько способов, чтобы убедиться, что это происходит в наших классах. Либо с инициализаторах или путем предоставления ценностей в декларации об имуществе, что я делаю здесь. Иногда, расчета этих начальных значений, как только экземпляр объекта не лучшее использование наших приложений времени. Представьте себе, в нашем классе, что у нас есть свойство, называемое бонус. И иногда мы будем использовать это свойство, а иногда и мы не будем.Проблема здесь, что бонус не предоставляется буквальное значение, которое он собирается получить его значение из другой функции под названием getDailyBonus в моем примере здесь, что мы можем считать потребности, чтобы сделать некоторые комплексной переработки, чтобы понять это.

Ладно, это действительно просто генерации случайного числа, но давайте представим, это должно выйти к сети или получить значение из некоторого нетривиального вычисления.Дело в том, когда я создаю экземпляр этого класса, что произойдет в том, что Swift будет идти вперед и инициализировать все эти свойства уровня экземпляра, и это будет причиной того, что функция будет называться я могу даже видеть результаты, что на детской площадке здесь. Я вижу, что этот новый объект, который был создан действительно есть, что данные внутри него. Я действительно не нужно вызывать эту функцию, если я не нужен доступ к этим свойством.

Один из способов, это я мог бы сделать это по желанию, используя знак вопроса я мог определить бонус в виде дополнительного Int. Тогда начнем добавлять некоторую логику к нему так, что, когда мне нужно получить доступ, это свойство проверить его за то, что ноль, и если он равен нулю, то мы пойдем выбирать это значение. Но другой способ, более простой способ, что у Свифта мы можем сделать это ленивый собственности. С ленивой собственности мы описываем начальное значение так же, как мы бы нормально, но Свифт не будет беспокоить на самом деле инициализации недвижимость пока кто-то не попытается получить к нему доступ.

И это невероятно легко, все, что я сделать, это добавить слово ленивый до нашей вар декларации. Теперь обратите внимание на немедленное разницу без слова ленивый. Когда я экземпляра объекта, я могу видеть результаты здесь, что эта функция вызывается, она выводит эту печатать строку в верхней генерирует случайное число. Но если я ставлю это слово ленивый назад перед ней вызов функции исчезает это не происходит прямо сейчас.Объект описания себя как имеющие имя John Doe, ноль баллов и бонус в настоящее время равна нулю.

Но в отличие от обязательно, я не придется беспокоиться об этом бонус бытия ноль, у меня нет, чтобы проверить его за то, что ноль, у меня нет, чтобы развернуть его. Потому что как только я пытаюсь получить доступ к ленивый собственность, я просто хочу, чтобы сделать это, как только это экземпляр я собираюсь идти вперед и распечатать все newPlayer.bonus является то, что собирается вызвать Свифт сразу инициализировать его он будет вызывать функцию, она получит значение, и он вернется, как если бы это имело значение все вместе. Он всегда будет иметь значение, если я пытаюсь его использовать.

Одна последняя вещь, чтобы отметить, ленивые свойства всегда переменные. Это всегда ленивый Вар, это ошибка компиляции, если вы попробуете и сказать ленивый аренду. Это потому, что под капотом, состояние этой части данных на самом деле меняет может начаться нуля и потом дать значение. Это не будет разрешено с константой, должна быть предоставлена установленное значение, как только объект инициализирован.

Adding property observers

- Swift has a great way to monitor changes to the state of our objects by adding something called property observers. These are a very easy way to automatically run some code whenever you change a property value. So taking this simple class definition, I'm going to add observers to this stored property called name. This won't change anything about how we would normally use this property. With name first what I'm going to do is add a code block right at the end just the opening and closing curly brace. Inside that, I can add two more code blocks with the names willSet and after that didSet.

These are our property observers, these are now automatically called for any change to this property. WillSet is called just before it's about to change, and didSet is called just after. You can use one or the other or both or of course, neither. I'm going to add a line to willSet in here, just a printline of about to change name to. What happens is we get passed in an implicit parameter that's called newValue. So willSet knows what it's about to change to.

The flip-side of that is didSet, which gets called afterwards, gets passed in an implicit parameter which is called oldValue. If this property is defined as a string, newValue and oldValue will be a string. If this property is defined as an int, they'll be an integer, and so on. And that's it, that is property observers. Now what I want to see is to see the effect of this we need to make a change to this object. Down here I'm instantiating a new instance of the player class and then what I'll do is I'll go ahead and say newPlayer.name equals Shelly Evans.

We see in the playground just the state of that object but we're not seeing the about to change name to or have changed name from messages. What I need to do is just open up the value history button so I can see the console output. But if I see that, we have the two messages. About to change name to Shelly Evans and have changed name from John Doe. That's new value and the old value that we're seeing. Notice that these are not called for the initialization of the property, they're not called when we first change it to John Doe, the way it was defined in the class itself.

That's because we can always assume the property is given an initial value. Observers take effect after initialization. They are only called when the property is changed. You can, if you want, change the name of the implicit parameter to these blocks if you don't like newValue or oldValue, say if I wanted this to be called new name, all I can do is after the willSet word, I can just put newName in parenthesis that will change the name of the implicit parameter and that's what I'd have to use inside this willSet block.

Having said that, I think newValue and oldValue are a pretty good fit for that information for that data. The only other thing to point out is you cannot add property observers to lazy properties like this one, just two regular stored properties. And that is it for property observers.

Adding property observers Добавление наблюдателей собственности

- Swift есть отличный способ, чтобы следить за изменениями в состоянии наших объектов, добавляя что-то называется наблюдателей собственности. Это очень простой способ, чтобы автоматически запустить код каждый раз при изменении значения свойства. Так что, это простое определение класса, я собираюсь добавить наблюдателей на этой хранимой собственности называется именем. Это что-нибудь о том, как мы обычно используют это свойство не изменится. С именем сначала, что я собираюсь сделать, это добавить блок кода в конце просто открытие и закрытие фигурную скобку. Внутри, что я могу добавить еще два кодовых блоков с именами willSet и после этого didSet.

Это наши наблюдатели собственности, в настоящее время они автоматически вызывается при любом изменении этого свойства. WillSet называется как раз перед его вот-вот изменится, и didSet называется сразу после. Вы можете использовать один или другой или оба или конечно, тоже. Я собираюсь добавить строку в willSet здесь, только Printline около изменить имя. Что происходит, является мы получаем прошел в неявный параметр, который называется новое_значение. Так willSet знает, что это вот-вот изменится.

Оборотной стороной этого является didSet, который вызывается после этого, получает принят в неявный параметр, который называется OldValue. Если это свойство определяется как строка, новое_значение и OldValue будет строка. Если это свойство определено как INT, они будут целое, и так далее. И это все, что наблюдатели собственности. Теперь то, что я хочу видеть, чтобы увидеть эффект этого нужно внести изменения в этот объект. Здесь, внизу, я экземпляра нового экземпляра класса игрока, а затем, что я буду делать, я буду идти вперед и сказать newPlayer.name равно Шелли Эванс.

Мы видим, на детской площадке просто состояние этого объекта, но мы не видим вот изменить имя или сменили название из сообщений. Что мне нужно сделать, это просто откройте кнопку История значение, поэтому я могу увидеть выход консоли. Но если я вижу, что у нас есть два сообщения. О том, чтобы изменить имя Шелли Эванс и сменили название от Джона Доу. Это новое значение и старое значение, что мы видим. Обратите внимание, что они не призывали к инициализации собственности, они не называют, когда мы сначала изменить его на John Doe, как она была определена в самом классе.

Это потому, что мы всегда можем предположить, свойство присваивается начальное значение. Наблюдатели вступают в силу после инициализации. Они называются только тогда, когда свойство меняется. Вы можете, если вы хотите изменить имя неявного параметра этих блоков, если вам не нравится новое_значение или OldValue, скажем, если я хотел, чтобы это можно назвать новое имя, все, что я могу сделать, это после willSet слова, я могу просто поставить NEWNAME в скобках, что будет изменить имя неявного параметра, и вот что я должен был бы использовать внутри этой willSet блока.

Сказав, что, я думаю, новое_значение и OldValue являются довольно хорошо подходит для этой информации для этих данных.Единственное, что бы отметить, что вы не можете добавить наблюдателей собственности на ленивых свойств, как этот, только два обычных хранимых свойств. И что это для наблюдателей собственности.

Understanding access modifiers in Swift

- And the final thing to cover in this section is access levels or access modifiers. It's common in many object oriented languages to have key words like private and public that can be attached to your classes, to your methods and properties, to control how visible and usable they are from elsewhere in the application or even from other applications. In Swift we have three such keywords, public, private, and internal. Marking a method or property or class as private means it's now only accessible from within the same source code file.

Attempting to call it from anywhere else will fail. Now internal means that this class, this method, or this property, is accessible from any code that's compiled into the same module. Now this is the default level for Swift, meaning that in a typical Xcode project you can access classes, properties, methods, that are written in separate code files as long as they're all part of the same project and compiled together into the same module. So if you don't use any of these keywords, any of these access modifiers, it is as if you'd written internal on your classes, on your methods and properties.

And then there's public that opens things up a bit. Marking a class as being public with public methods means that it's also callable from outside your own compiled module so by any other module that has imported your code. This is the term you would use if you were creating say a framework that you wanted to be reusable across multiple different projects. To use these, we just use one of these keywords in front of the method or class or property we want to affect. And one thing to understand about this is the levels of nesting that are going on.

You can't, for example, just mark a single property or method as public if you haven't also marked the class as public. It doesn't make sense to say you have a publicly accessible method but the class it's in is internal and not publicly accessible. As a general principle of object orientation, you'll want access levels that are on the restrictive side and only allow outside access to any data or behavior when it is a proven need.

Understanding access modifiers in Swift

Понимание модификаторы доступа в Swift

- И последнее, что для покрытия в этом разделе Уровни доступа или модификаторы доступа. Это распространено во многих объектно-ориентированных языках, чтобы иметь ключевые слова, как частные и государственные, которые могут быть присоединены к классам, ваши методы и свойства, чтобы контролировать, как видимое и используемое они из в любом месте приложения или даже из других приложений. В Свифт мы имеем три таких ключевых слов, государственных, частных, так и внутренние. Маркировка метод или свойство или класс как частные значит, что теперь доступны только в пределах того же файла с исходным кодом.

Попытка вызвать его из нигде не удастся. Теперь внутренний означает, что этот класс, этот метод, или это свойство доступно из любого кода, который компилируется в одном модуле. Теперь это уровень по умолчанию для Свифт, это означает, что в типичном Xcode проекта вы можете получить доступ к классам, свойства, методы, которые написаны в отдельных файлах кода до тех пор, как они все это часть того же проекта и скомпилированные вместе в то же самое модуль. Так что, если вы не используете какой-либо из этих ключевых слов, любой из этих модификаторов доступа, это как если бы вы написали внутренний на ваших классов, на ваших методов и свойств.

А тут еще общественности, что открывает вещи немного. Маркировка класс в качестве публике с открытых методов означает, что это также вызывается из вне вашей собственной скомпилированного модуля со стороны любого другого модуля, который импортного кода. Это термин, который вы будете использовать, если вы создавали сказать основу, что вы хотели, чтобы быть использоваться несколькими различными проектами. Чтобы использовать их, мы просто используем одну из этих ключевых слов в передней части метода или класса, или имущества, который мы хотим повлиять. И еще одна вещь, чтобы понять об этом является уровень вложенности, что происходит.

Вы не можете, например, просто отметьте одно свойство или как метод общественности, если вы не также отмечен класс как общественности. Это не имеет смысла, у вас есть общедоступный метод, но класс это в является внутренним и не является общедоступной. В качестве общего принципа объектной ориентации, вы хотите, уровни доступа, которые находятся на ограничительной части и только позволит внешний доступ к любым данным или поведения, когда это доказанной необходимости.

Introduction

Welcome

What you should know

1. Core Syntax

The structure of Swift

Writing Swift in playgrounds

Declaring variables

Creating constants

Printing values and working with string interpolation

Converting values

Writing if statements

Using the switch statement

Creating loops in Swift

Defining functions

2. Complex Types

Creating and using arrays

Using dictionaries

Understanding tuples

Creating optional variables

Defining and using enumerations

Writing closures

3. Creating Classes

Defining and instantiating classes

Adding initializers to a class

Using inheritance

Creating computed properties

Using type properties and methods

Defining lazy properties

Adding property observers

Understanding access modifiers in Swift

4. Taking It Further

Working with structures

Using basic operators

Comparison, equality, and identity

Advanced operators

Importing frameworks and using Objective-C classes

5. Advanced Language Features

Type checking and downcasting

Using Any and AnyObject references

Supporting protocols

Adding functionality with extensions

Using generics in Swift

Conclusion

Wrapping up

117

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]