iOS Small Talks: Klasy i struktury w języku Swift

iOS Small Talks: Klasy i struktury w języku Swift

Język Swift wprowadził znaczne udoskonalenie struktur, w związku z czym stały się one ciekawą alternatywą dla klas w wielu przypadkach. Spora część możliwości klasy i struktury jest analogiczna, jednak istnieje kilka różnic, dzięki którym warto rozważyć przydatność każdej z form w konkretnej sytuacji.

Wspólne cechy klas i struktur

  • właściwości przechowujące konkretne wartości,
  • definiowanie metod w celu zapewnienia funkcjonalności,
  • definiowanie subskryptów, za pomocą których można uzyskać dostęp do wybranej wartości,
  • inicjalizatory, dzięki którym nadajemy stan początkowy,
  • rozszerzanie funkcjonalności poza podstawową implementację,
  • dostosowywanie się do protokołów.

Najważniejsze różnice

  • możliwość dziedziczenia dla klas oraz jej brak dla struktury,
  • dla klasy można zdefiniować deinicjalizatory,
  • klasy są typem przekazywanym przez referencję, natomiast struktury przekazywane są przez wartość.

Tworzenie instancji klasy i struktury jest bardzo podobne. Różni się jedynie słowem kluczowym class lub struct. Dostęp do właściwości również jest analogiczny. Różnicę dostrzeżemy natomiast w momencie tworzenia instancji. Dla struktury na podstawie wszystkich właściwości zostanie automatycznie utworzony inteligentny inicjalizator.

Załóżmy, że nasza struktura wygląda tak, jak ta poniżej:

struct Coordinates {
            var x : Float
            var y : Float
            var z : Float
}

Zostanie dla niej utworzony następujący inicjalizator, gdzie wartości x,y,z należy oczywiście uzupełnić:

var myCoordinates = Coordinates(x: , y: , z: )

Z racji faktu, iż klasa jest typem referencyjnym, natomiast struktura wartościowym, wynikać będzie różnica w zachowaniu w momencie przypisania do nowej instancji już utworzonego obiektu i wykonaniu operacji na tej instancji. Przykładowo dla wyżej wymienionej struktury:

var myCoordinates = Coordinates(x: 0 , y: 0, z: 0)
var anotherCoordinates = myCoordinates
anotherCoordinates.x = 22

Po wykonaniu takich operacji właściwość x dla myCoordinates nadal wynosi 0, natomiast dla anotherCoordinates 22. Dzieje się tak za sprawą tego, iż w momencie przypisania myCoordinates do anotherCoordinates nie została przekazana referencja do obiektu, a jego kopia. W momencie wykonania analogicznych operacji na instancjach klasy wartość zmiennej x dla obu z nich wynosiłaby aktualnie 22.

W przypadku użycia instancji struktury jako parametru metody, również wysyłana jest kopia, a w związku z tym zmiany wykonane w trakcie działania metody zostaną zapamiętane jedynie lokalnie w jej zakresie. Aby zmiany zostały uwzględnione w naszej instancji globalnie, należy oznaczyć parametr metody jako inout. Dzięki temu znacznikowi, parametrom przekazywanym do funkcji przez wartość przypisane zostają zmiany wykonane w trakcie funkcji.

func changeCoordinates(inout coordinates: Coordinates) {
	coordinates.x = 88
	coordinates.y = 100
}

changeCoordinates(&myCoordinates)

Po wykonaniu takich działań wartości x oraz y instancji myCoordinates będą wynosić 88 oraz 100. Warto zauważyć, że w tym przypadku, w przeciwieństwie do standardowego podawania parametrów funkcji, parametr myCoordinates poprzedzony jest znakiem &.

Kolejną zauważalną różnicą są następstwa wynikające ze zdefiniowania instancji klasy bądź też struktury jako stałej. Dla klasy po utworzeniu stałej obiektowej nie można zmienić obiektu do którego się odnosi, natomiast możliwe jest edytowanie właściwości obiektu przypisanego do tej stałej. Dla struktury zaś właściwości obiektu również stają się niezmienne. Obrazuje to poniższy przykład:

  • dla klasy:
let myCoordinates = Coordinates(x: 0 , y: 0, z: 0)
var anotherCoordinates = myCoordinates

myCoordinates = anotherCoordinates  // błąd

myCoordinates.x = 22 // dozwolona operacja
  • dla struktury:
let myCoordinates = Coordinates(x: 0 , y: 0, z: 0)
var anotherCoordinates = myCoordinates
myCoordinates = anotherCoordinates  // błąd
myCoordinates.x = 22 // również błąd

Struktury wprowadzają również zabezpieczenie dotyczące metod, które zmieniają właściwości owej struktury. Na podstawie powyższej struktury dodanie do niej metody:

func increaseByTwo() {
            self.x = self.x + 2
}

jest niedozwolone, gdyż zmienia ona parametr self. Aby umożliwić metodzie takie operacje, należy dodać do niej słowo kluczowe mutating.

mutating func increaseByTwo() {
            self.x = self.x + 2
}

Teraz kompilator już nie potraktuje tej metody jako błąd.

Struktury czy klasy?

Na podstawie różnych możliwości, oferowanych przez struktury oraz klasy, nasuwa się pytanie, kiedy należy stosować struktury, a kiedy też klasy. Dokumentacja firmy Apple wspomina o tym, iż podstawowym celem struktury jest przechowywanie względnie prostych wartości. Wartości te w momencie przesyłania instancji struktury powinny być wartościami, które chcemy kopiować, a nie podawać ich referencje. Przy wyborze warto pamiętać również, o tym że struktury nie umożliwiają dziedziczenia.

Jako dobry przykład struktury zostały wymienione:

  • rozmiary kształtów geometrycznych,
  • różnego rodzaju współrzędne.

W przypadku napotkania kandydata odpowiedniego na strukturę, warto jej użyć, ponieważ jej wydajność jest lepsza niż wydajność klasy dla obiektów zawierających jedynie kilka prostych właściwości.

Na koniec warto wspomnieć, iż w języku Swift tablice oraz słowniki również są strukturami. W związku z tym faktem w momencie przypisania jednej instancji tablicy innej tablicy dane są kopiowane, co skutkuje tym, że zmiana w jednej tablicy nie jest odzwierciedlona w drugiej. W Objective-C aby uzyskać takie zachowanie należało celowo utworzyć kopię tablicy za pomocą metody copy.

Dowiedz się więcej

Wycena projektu

Opowiedz nam o swoim projekcie i napisz, jak możemy Ci pomóc.

Dlaczego warto rozwijać z nami projekty?

Logo Mobile Trends Awards

Mobile Trends Awards 2021

Wygrana w kategorii
ŻYCIE CODZIENNE

Nagroda Legalnych Bukmacherów

Nagroda Legalnych Bukmacherów 2019

Najlepsza aplikacja mobilna

Mobile Trends Awards logo

Mobile Trends Awards 2023

Wygrana w kategorii
MCOMMERCE ROZWÓJ

23

opinie klientów

Clutch logo