Всичко, което трябва да знаете за съхранените и изчислените свойства

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

Казано с прости думи, свойствата са променливи и константи, които съхраняват стойности и които ние декларираме в класове, структури и изброявания на Swift. Но свойствата не са уникални за Swift. Срещаме ги във всеки език за обектно-ориентирано програмиране (ООП).

Независимо от това, два нови термина навлизат в свойствата за разиграване достатъчно скоро — storedиcomputed. Въпреки че и двете обясняват значението си по някакъв начин, човек разбира какво всъщност представляват те едва след като ги изследва.

Често се случва програмистите да пишат код, без дори да са чували за съществуването на тези концепции. Факт е, че можем да пишем цели приложения, без да знаем и най-малката подробност за тях. И така, защо е необходимо да научим за тях?

Е, първо, тъй като съхранените и изчислените свойства съществуват като концепции в езика Swift, те се превръщат в задължително знание, което всеки трябва да разбира и притежава.

В крайна сметка и както ще разберете в тази публикация, това не е трудна тема. Но освен това, знаейки какво представляват те и какво могат да предложат като цяло, може да ни помогне да променим начина, по който кодираме и да придобием по-добри навици за програмиране.

И така, нека се потопим заедно в някои повече подробности относно съхранените и изчислените свойства в Swift, като ги подчертаем чрез няколко прости примера и обяснения.

Съхранени свойства

Съхранените свойства са променливи или константи, които съхраняват стойности на екземпляри на класове или структури. Въпреки че звучи очевидно, стойностите, присвоени на променливи, могат да бъдат променяни по всяко време. Напротив, стойностите, първоначално присвоени на константите, не могат да бъдат променени по-късно.

В зависимост от нуждите на програмата, която внедряваме, можем да присвоим стойности по подразбиране на свойства заедно с тяхната декларация.

Ако има свойства само с техния тип данни, без стойност по подразбиране и не са декларирани като незадължителни, тогава първоначалните стойности трябва да бъдат предоставени по време на инициализацията на екземпляра от типа, към който принадлежат.

Обърнете внимание, че за съхранени свойства, които са константи, стойността по подразбиране или първоначалната стойност е това, което свойството ще съдържа за целия живот на екземпляра; константите са неизменни и не се променят. Също така можем да декларираме съхранените свойства като незадължителни.

Следният кодов фрагмент демонстрира всичко това:

В класа Programmer по-горе има декларирани четири съхранени свойства. Свойството name е от тип String и няма стойност по подразбиране; това означава, че ще е необходимо да предоставим такъв, когато ще инициализираме екземпляр на класа.

Свойството language, което трябва да поддържа езика за програмиране, с който програмистът има опит, е константа. Подобно на предишното, това съхранено свойство ще получи своята стойност в момента на инициализация на екземпляра, но за разлика от това няма да се промени след това.

Свойството yearsOfExperience е декларирано със стойност по подразбиране. Тъй като това е променлива, можем да променим стойността му, когато пожелаем по-късно в бъдеще. Също така забележете, че ние не задаваме явен тип на свойството, въпреки че би било напълно добре, ако бяхме направили това. Той се извежда автоматично от първоначалната стойност, която му е присвоена.

И накрая, свойството secondLanguage не е задължително и трябва да съхранява друг език за програмиране, с който програмистът е запознат.

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

Ако запазим горната реализация такава, каквато е, тогава първите две съхранени свойства ще накарат Xcode да покаже грешка, казвайки, че класът няма инициализатори. В случаи като този, когато типът контейнер е клас, е необходимо да се приложи персонализиран инициализатор, където ще присвоим първоначални стойности на тези свойства:

Нека сега създадем екземпляр на Programmer, за да видим съхранените по-горе свойства в действие. Първите две свойства ще получат стойност при инициализация:

Тъй като name е променлива, можем да я променим, когато пожелаем:

programmer.name = "Gabe"

Не можем обаче да направим същото със съхраненото свойство language. Това е константа, така че е неизменно:

По отношение на другите две съхранени свойства, можем да им присвоим стойности, когато това е подходящо:

И тъй като те са променливи, можем свободно да ги променяме, когато е необходимо. Особено последното също може да стане нула; беше декларирана като незадължителна променлива.

Съхранени свойства в структури

Само няколко реда по-рано инициализирахме екземпляр Programmer и го присвоихме на променлива с помощта на ключовата дума var. Можехме да използваме let и да присвоим екземпляра и на константа — все още можем да използваме всички съхранени свойства, както е показано по-горе:

Нещата обаче не биха били същите, ако Programmer беше структура вместо клас:

В този случай, когато Programmer е структура, автоматично се предоставя инициализатор по подразбиране — следователно можем просто да пропуснем внедряването на персонализиран, както беше показано по-рано с класа.

Инициализирането сега на екземпляр Programmer и присвояването на променлива ще работи точно както се очаква без никакви проблеми. Но следният ред, който присвоява екземпляра на константа, декларирана с ключовата дума let, задейства грешка в Xcode:

Само защото структурата Programmer е тип стойност, всички нейни съхранени свойства също стават константи подобно на екземпляра programmer. Това се случва независимо дали сме декларирали повечето от тях като променливи.

Това обаче не е така с класовете; те са референтни типове и променливите на даден екземпляр могат да бъдат модифицирани, дори ако екземплярът е бил присвоен на константа.

Така че, като правило, присвоете екземпляри на структури на променливи, за да промените съхранените свойства. От друга страна, не се колебайте да присвоите екземпляри на класове на променливи или константи. Първото е задължително в случай, че искате да направите инстанцията нула в някакъв момент в бъдещето.

Изчислени свойства

За разлика от съхранените свойства, изчислените свойства не съхраняват никакви стойности. Това, което правят обаче, е да върнат и по избор да зададат стойността на други съхранени свойства, обикновено след някои изчисления.

За да направят това, те предоставят agetterиsetter съответно за извличане и съхраняване на стойности. За да стане ясно, разгледайте следната структура:

Структурата Angle има съхранено свойство, наречено degrees за съхраняване на ъгъл в градуси. Но можем също да изразим ъгъл в радиани, така че структурата Angle дефинира и свойството rads. Това не е съхранено, а изчислено свойство.

Най-забележимото нещо в свойството rads е неговият метод за получаване и настройка. В тялото на rads, дефинирано от фигурните скоби, има съответно get и set блок.

В първия върнатата стойност е радианите, след като е изчислена въз основа на текущата стойност на свойството degrees. В инструмента за настройка ние преобразуваме дадената стойност в радиани в градуси и я съхраняваме в съхраненото свойство degrees.

Вижте, че стойността на радианите в сетера по-горе е представена с името newRads. Предоставянето му обаче не е задължително, тъй като има стенограма за използване; можем да го пропуснем и в този случай можем да получим достъп до новата стойност с името по подразбиране newValue:

Както можете да разберете, това, което успяхме да направим по-горе, е да представим ъгъл по два различни начина; както в градуси, така и в радиани. Но въпреки че декларирахме две свойства, само едно от тях всъщност съхранява стойност.

Другият изчислява стойността си в движение и когато е зададен, предоставените радиани се преобразуват и съхраняват като градуси. Това ясно демонстрира удобството и мощността, които изчислените свойства предлагат; не са необходими допълнителни допълнителни действия за преобразуване на градуси в радиани или обратното.

Изчислени свойства само за четене

Внедряването на инструмента за получаване на изчислено свойство е задължително. Това обаче за сетера е абсолютно незадължително и зависи от изчисленото свойство, което дефинираме.

За да видите пример за това, да предположим, че имаме структура за поддържане на температурни стойности. За тази цел имаме масив и изчислено свойство, за да получим средната стойност на температурата:

Забележете, че тук не съществува сетер и не би имало смисъл, ако съществуваше. В случаи като горния, когато няма настройка, тогава изчисленото свойство се нарича само за четене.

Начинът, по който пишем изчислени свойства само за четене, може да бъде опростен, като се отървем от няколко неща. Първото е тялото get; тъй като няма сетер, вече не е необходимо изрично да го пишете:

Вторият ход към превръщането на изчисленото свойство само за четене в „по-леко“ е чрез премахване на ключовата дума return. Поддържането му в отделни изрази не е задължително:

Изчисленото свойство сега е по-опростено, тъй като изричният метод за получаване и ключовата дума return липсват в имплементацията.

Изчислени свойства вместо методи

Доста често срещано е изчислените свойства да се прилагат вместо методи, стига да не са необходими аргументи за предоставяне. И последният пример точно по-горе може да ви помогне да изясните това.

Да предположим за момент, че изчисленото свойство average не съществува в структурата Температури. Изискването за получаване на средната температура обаче все още съществува. Обикновено бихме внедрили метод за получаване на тази стойност така:

Въпреки че разликите са малки по отношение на синтаксиса, вероятно е по-удобно и малко по-просто да получите средната температура като изчислено свойство, вместо да дефинирате метод.

Всъщност и двата начина са правилни и това е най-вече въпрос на навик за кодиране. Но тъй като изчислените свойства често могат да имат същите резултати като методите и като се има предвид, че те са синтактично по-прости, печалбата тук би била по-малко, по-ясен и по-четлив код.

Има едно последно нещо, което трябва да се отбележи по отношение на изчислените свойства. Подобно на методите, при които указваме връщания тип, също е необходимо изрично да зададем типа на изчисленото свойство.

Това не е случаят със съхранените имоти. Както бе споменато по-рано, типът там може да бъде изведен въз основа на стойността по подразбиране, присвоена на свойството.

Заключение

Изследването на съхранените и изчислените свойства приключва тук и тази публикация обобщава почти всичко, което трябва да знаете за тях.

Много е вероятно вече да сте познавали много от представените теми дори извън опит; особено за съхранените свойства, тъй като това е, което всички използваме предимно.

От друга страна, изчислените свойства също са интересни, тъй като освен първоначалната им цел, могат да се използват и вместо методи. Надявам се, че сте научили нещо ново тук днес, особено ако сте новодошъл в Swift. Благодарим ви, че прочетохте и следете за други интересни теми!

Първоначално публикувано на адрес https://serialcoder.dev на 13 август 2021 г.