Dlaczego Warto Wybrać Struct Zamiast Klasy?

Bawiąc się Swiftem, pochodzącym z tła Javy, dlaczego chcesz wybrać strukturę zamiast klasy? Wygląda na to, że to to samo, ze strukturą oferującą mniejszą funkcjonalność. Dlaczego więc go wybrać?

Author: Honey, 2014-06-15

15 answers

Według bardzo popularnego WWDC 2015 talk Protocol Oriented Programowanie w języku Swift (wideo, transcript ), Swift dostarcza wiele funkcji, które w wielu okolicznościach czynią struktury lepszymi niż klasy.

Struktury są preferowane, jeśli są stosunkowo małe i możliwe do skopiowania, ponieważ kopiowanie jest o wiele bezpieczniejsze niż posiadanie wielu odwołań do tej samej instancji, co ma miejsce w przypadku klas. Jest to szczególnie ważne przy przekazywaniu zmiennej do wielu klas i / lub w środowisko wielowątkowe. Jeśli zawsze możesz wysłać kopię zmiennej do innych miejsc, nigdy nie musisz się martwić o to, że inne miejsce zmieni wartość zmiennej pod tobą.

W przypadku struktur nie ma potrzeby martwić się o wycieki pamięci lub wiele wątków ścigających się w celu uzyskania dostępu/modyfikacji pojedynczej instancji zmiennej. (Dla bardziej technicznie myślących wyjątkiem jest przechwytywanie struktury wewnątrz zamknięcia, ponieważ wtedy jest to rzeczywiście przechwytywanie odniesienia do instancja, chyba że wyraźnie zaznaczasz ją do skopiowania).

Klasy mogą również stać się nadęte, ponieważ klasa może dziedziczyć tylko z jednej klasy nadrzędnej. To zachęca nas do tworzenia ogromnych superklas, które obejmują wiele różnych umiejętności, które są luźno ze sobą powiązane. Korzystanie z protokołów, szczególnie z rozszerzeniami protokołów, w których można zapewnić implementacje protokołów, pozwala wyeliminować potrzebę tworzenia klas w celu osiągnięcia tego rodzaju zachowania.

Rozmowa przedstawia te scenariusze, w których preferowane są klasy:

  • kopiowanie lub porównywanie instancji nie ma sensu (np. okno)
  • Czas życia instancji jest związany z efektami zewnętrznymi (np.]}
  • instancje są po prostu "umywalkami" --tylko do zapisu łączami do stanu zewnętrznego (np. CGContext)

Oznacza to, że struktury powinny być domyślne, A klasy powinny być awaryjne.

Z drugiej strony język programowania Swift dokumentacja jest nieco sprzeczna:

Instancje struktury są zawsze przekazywane przez wartość, a klasa instancje są zawsze przekazywane przez odniesienie. Oznacza to, że są nadaje się do różnego rodzaju zadań. Jak wziąć pod uwagę dane konstrukcji i funkcjonalności, których potrzebujesz do projektu, zdecyduj czy każda konstrukcja danych powinna być zdefiniowana jako klasa czy jako struktura.

Jako ogólne wytyczne rozważ tworzenie struktury, gdy jeden lub więcej z tych warunki:

  • głównym celem struktury jest hermetyzacja kilku stosunkowo prostych wartości danych.
  • uzasadnione jest oczekiwanie, że zamknięte wartości będą kopiowane, a nie odwoływane, gdy przypisujesz lub przekazujesz przykład tej struktury.
  • wszelkie właściwości przechowywane przez strukturę są same w sobie typami wartości, które również powinny być kopiowane, a nie odwoływane.
  • struktura nie musi Dziedzicz Właściwości lub zachowanie z innego istniejącego typu.

Przykłady dobrych kandydatów do struktur to:

  • Rozmiar geometrycznego kształtu, być może zawierający właściwość width i height, oba typu Double.
  • sposób odwoływania się do zakresów w ramach serii, być może enkapsulujących właściwość start i właściwość length, oba typu Int.
  • punkt w układzie współrzędnych 3D, być może zawierający właściwości x, y i z, każdy z typu Double.

We wszystkich innych przypadkach zdefiniuj klasę i utwórz instancje tej klasy być zarządzane i przekazywane przez odniesienie. W praktyce oznacza to, że większość niestandardowych konstrukcji danych powinna być klasami, a nie strukturami.

Tutaj jest twierdzenie, że powinniśmy domyślnie używać klas i używać struktur tylko w określonych okolicznościach. Ostatecznie, trzeba zrozumieć rzeczywisty wpływ typów wartości vs. typy odniesienia, a następnie można zrobić świadomą decyzję o tym, kiedy używać struktur lub klas. Należy również pamiętać, że koncepcje te zawsze ewoluują, a dokumentacja języka programowania Swift została napisana przed rozpoczęciem rozmowy o programowaniu zorientowanym na protokół.

 466
Author: drewag,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-03 07:44:40

Ponieważ instancje struct są przydzielane na stosie, a instancje klas na stosie, struktury mogą być czasami drastycznie szybsze.

Jednak zawsze należy zmierzyć go samodzielnie i zdecydować w oparciu o swój unikalny przypadek użycia.

Rozważ poniższy przykład, który demonstruje 2 strategie owijania typu danych Int za pomocą struct i class. Używam 10 powtarzających się wartości, aby lepiej odzwierciedlić rzeczywisty świat, w którym masz wiele pola.

class Int10Class {
    let value1, value2, value3, value4, value5, value6, value7, value8, value9, value10: Int
    init(_ val: Int) {
        self.value1 = val
        self.value2 = val
        self.value3 = val
        self.value4 = val
        self.value5 = val
        self.value6 = val
        self.value7 = val
        self.value8 = val
        self.value9 = val
        self.value10 = val
    }
}

struct Int10Struct {
    let value1, value2, value3, value4, value5, value6, value7, value8, value9, value10: Int
    init(_ val: Int) {
        self.value1 = val
        self.value2 = val
        self.value3 = val
        self.value4 = val
        self.value5 = val
        self.value6 = val
        self.value7 = val
        self.value8 = val
        self.value9 = val
        self.value10 = val
    }
}

func + (x: Int10Class, y: Int10Class) -> Int10Class {
    return IntClass(x.value + y.value)
}

func + (x: Int10Struct, y: Int10Struct) -> Int10Struct {
    return IntStruct(x.value + y.value)
}

Wydajność mierzona jest za pomocą

// Measure Int10Class
measure("class (10 fields)") {
    var x = Int10Class(0)
    for _ in 1...10000000 {
        x = x + Int10Class(1)
    }
}

// Measure Int10Struct
measure("struct (10 fields)") {
    var y = Int10Struct(0)
    for _ in 1...10000000 {
        y = y + Int10Struct(1)
    }
}

func measure(name: String, @noescape block: () -> ()) {
    let t0 = CACurrentMediaTime()

    block()

    let dt = CACurrentMediaTime() - t0
    print("\(name) -> \(dt)")
}

Kod można znaleźć na stronie https://github.com/knguyen2708/StructVsClassPerformance

Aktualizacja (27 Mar 2018):

W 2009 roku firma Microsoft wprowadziła do swojej oferty nową wersję oprogramowania dla iPhone 'a 6s i iOS 11.2.6, która jest dostępna w wersji 4.0, Xcode 9.2, Wersja Dla iPhone' a 6s i iOS 11.2.6.]}
  • class wersja zajęła 2.06 sekund
  • Wersja zajęła 4.17 E-08 sekund (50 000 000 razy szybciej)

(już nie średni przebieg wielokrotny, ponieważ wariancje są bardzo małe, poniżej 5%)

Uwaga : różnica jest o wiele mniej dramatyczna bez optymalizacji całego modułu. Byłbym zadowolony, gdyby ktoś mógł wskazać, co właściwie robi flaga.


Aktualizacja (7 maja 2016):

W wersji 2.2.1, Xcode 7.3, wersja na iPhone ' a 6s, iOS 9.3.1, średnia z 5 uruchomień, ustawienie kompilatora Swift To -O -whole-module-optimization:
  • class wersja wzięta 2.159942142 s
  • Wersja miała 5.83 E-08S (37.000.000 razy szybsza)

Notatka: Jak ktoś wspomniał, że w rzeczywistych scenariuszach, w strukturze będzie prawdopodobnie więcej niż 1 pole, dodałem testy dla struktur / klas z 10 polami zamiast 1. Co zaskakujące, wyniki nie różnią się zbytnio.


Oryginalne wyniki (1 czerwca 2014):

(uruchamiany na struct / class Z 1 polem, nie 10)

Od Swift 1.2, Xcode 6.3.2, działa Wydanie kompilacji na iPhone 5S, iOS 8.3, średnio na 5 uruchomień

  • class wersja zajęła 9.788332333 s
  • struct wersja trwała 0.010532942 s (900 razy szybciej)

Stare wyniki (z nieznanego czasu)

(uruchamiany na struct / class Z 1 polem, nie 10)

Z release build na moim MacBooku Pro:

  • wersja class zajęła 1.10082 sek
  • Wersja struct zajęła 0.02324 sek (50 razy szybciej)
 137
Author: Khanh Nguyen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-27 07:33:23

Podobieństwa między strukturami i klasami.

Stworzyłem do tego gist z prostymi przykładami. https://github.com/objc-swift/swift-classes-vs-structures

I różnice

1. Spadek.

Struktury nie mogą dziedziczyć w języku swift. Jeśli chcesz

class Vehicle{
}

class Car : Vehicle{
}
Idź na zajęcia.

2. Pass By

Struktury Swift przechodzą przez wartość, a instancje klas przez odniesienie.

Różnice Kontekstowe

Stała Struct i zmienne

Przykład (użyty na WWDC 2014)

struct Point{

   var x = 0.0;
   var y = 0.0;

} 

Definiuje punkt wywołany strukturą.

var point = Point(x:0.0,y:2.0)

Teraz, jeśli spróbuję zmienić X. to poprawne wyrażenie.

point.x = 5

Ale jeśli zdefiniowałem punkt jako stały.

let point = Point(x:0.0,y:2.0)
point.x = 5 //This will give compile time error.

W tym przypadku cały punkt jest niezmienna stała.

Jeśli użyłem punktu klasy zamiast tego jest to poprawne wyrażenie. Ponieważ w klasie niezmienna stała jest odniesieniem do samej klasy, a nie jej zmiennych instancji (chyba że te zmienne zdefiniowane jako stałe)

 55
Author: MadNik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-01 10:13:33

Oto kilka innych powodów do rozważenia:

  1. Struktury otrzymują automatyczny inicjator, którego nie trzeba w ogóle utrzymywać w kodzie.

    struct MorphProperty {
       var type : MorphPropertyValueType
       var key : String
       var value : AnyObject
    
       enum MorphPropertyValueType {
           case String, Int, Double
       }
     }
    
     var m = MorphProperty(type: .Int, key: "what", value: "blah")
    

Aby uzyskać to w klasie, musisz dodać inicjalizator i utrzymać inicjalizator...

  1. Podstawowe typy kolekcji, takie jak Array są strukturami. Im więcej ich używasz we własnym kodzie, tym bardziej przyzwyczaisz się do przekazywania wartości w przeciwieństwie do referencji. Na instancja:

    func removeLast(var array:[String]) {
       array.removeLast()
       println(array) // [one, two]
    }
    
    var someArray = ["one", "two", "three"]
    removeLast(someArray)
    println(someArray) // [one, two, three]
    
  2. Najwyraźniej niezmienność kontra zmienność to ogromny temat, ale wielu mądrych ludzi uważa, że niezmienność-struktury w tym przypadku-jest preferowana. Mutable vs immutable objects

 28
Author: Dan Rosenstark,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:26

Niektóre zalety:

  • automatycznie threadsafe z powodu braku możliwości udostępniania
  • używa mniej pamięci ze względu na brak isa i refcount (a w rzeczywistości jest przydzielany na stos)
  • metody są zawsze wysyłane statycznie, więc mogą być inlinowane (chociaż @final może to zrobić dla klas)
  • łatwiej rozumować (nie ma potrzeby "defensywnego kopiowania", jak to jest typowe dla NSArray, NSString, itp...) z tego samego powodu co bezpieczeństwo wątku
 18
Author: Catfish_Man,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-15 18:38:13

Zakładając, że wiemy, że Struct jest typem wartości , A klasa jest typem odniesienia .

Jeśli nie wiesz, co to jest typ wartości i typ odniesienia, zobacz Jaka jest różnica między przekazywaniem przez odniesienie a przekazywaniem przez wartość?

Na podstawie post mikeasha :

... Przyjrzyjmy się najpierw skrajnym, oczywistym przykładom. Liczbami całkowitymi są oczywiście można skopiować. Powinny to być typy wartości. Sieć gniazda nie mogą być rozsądnie kopiowane. Powinny być typami odniesienia. Punkty, jak w x, y pary, są kopiowalne. Powinny to być typy wartości. Kontroler, który dysk nie może być sensownie kopiowany. To powinno być odniesienie Typ.

Niektóre typy można skopiować, ale może nie być to coś, co chcesz to się zdarza cały czas. Sugeruje to, że powinny one być odniesienia typy. Na przykład można koncepcyjnie skopiować przycisk na ekranie. Kopia nie będzie do końca identyczna z oryginał. Kliknij na Kopia nie aktywuje oryginału. Kopia nie będzie zajmować tego samego lokalizacja na ekranie. Jeśli podasz przycisk wokół lub włożysz go do Nowa zmienna prawdopodobnie będziesz chciał odwołać się do oryginalnego przycisku, a chcesz zrobić kopię tylko wtedy, gdy jest to wyraźnie wymagane. Że oznacza, że typ przycisku powinien być typem odniesienia.

Kontrolery widoku i okien są podobnym przykładem. Mogą być kopiowalne, możliwe, ale to prawie nigdy tego, co chciałbyś zrobić. Powinny być typami odniesienia.

A co z typami modeli? Możesz mieć typ użytkownika reprezentujący użytkownika w Twoim systemie, lub typ przestępstwa reprezentujący działanie podjęte przez Użytkownik. Są one dość kopiowalne, więc prawdopodobnie powinny być wartościowe typy. Jednak prawdopodobnie chcesz aktualizacji do przestępstwa użytkownika dokonane w jedno miejsce w programie, aby być widocznym dla innych części programu. sugeruje to, że użytkownicy powinni być zarządzani przez jakiś użytkownik kontroler, który byłby typem odniesienia .

Kolekcje są ciekawym przypadkiem. Należą do nich takie rzeczy jak tablice i słowniki, a także ciągi. Czy można je skopiować? Oczywiście. Na kopiowanie czegoś, co chcesz zrobić łatwo i często? To mniej czysto.

Większość języków mówi " Nie " temu i sprawia, że ich zbiory odwołują się do typy. Tak jest w Objective-C i Javie, Pythonie i JavaScript i prawie każdy inny język, jaki przychodzi mi do głowy. (Jeden główny wyjątek jest C++ z typami kolekcji STL, ale C++ jest szalonym wariatem z świat języka, który robi wszystko dziwnie.)

Swift powiedział "tak", co oznacza, że typy takie jak Array i Dictionary oraz String są strukturami, a nie klasami. Są kopiowane na zlecenie, i przy przekazywaniu ich jako parametrów. Jest to całkowicie rozsądny wybór o ile kopia jest tania, co Swift bardzo się stara / align = "left" / ...

DODATKOWO nie Użyj klasy, gdy musisz nadpisać każdą instancję funkcji, tzn. nie mają one żadnej współdzielonej funkcjonalności .

Więc zamiast mieć kilka podklas klasy. Użyj kilku struktur zgodnych z protokołem.

 13
Author: Honey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-11 15:53:05

Struktura jest znacznie szybsza niż Klasa. Ponadto, jeśli potrzebujesz dziedziczenia, musisz użyć klasy. Najważniejszym punktem jest to, że klasa jest typem odniesienia, podczas gdy struktura jest typem wartości. na przykład,

class Flight {
    var id:Int?
    var description:String?
    var destination:String?
    var airlines:String?
    init(){
        id = 100
        description = "first ever flight of Virgin Airlines"
        destination = "london"
        airlines = "Virgin Airlines"
    } 
}

struct Flight2 {
    var id:Int
    var description:String
    var destination:String
    var airlines:String  
}

Teraz pozwala utworzyć instancję obu.

var flightA = Flight()

var flightB = Flight2.init(id: 100, description:"first ever flight of Virgin Airlines", destination:"london" , airlines:"Virgin Airlines" )

Teraz pozwala przekazać te instancje dwóm funkcjom, które modyfikują id, opis, miejsce docelowe itp..

func modifyFlight(flight:Flight) -> Void {
    flight.id = 200
    flight.description = "second flight of Virgin Airlines"
    flight.destination = "new york"
    flight.airlines = "Virgin Airlines"
}

Również,

func modifyFlight2(flight2: Flight2) -> Void {
    var passedFlight = flight2
    passedFlight.id = 200
    passedFlight.description = "second flight from virgin airlines" 
}

Więc,

modifyFlight(flight: flightA)
modifyFlight2(flight2: flightB)

Teraz, jeśli wydrukujemy identyfikator i opis lotu, get

id = 200
description = "second flight of Virgin Airlines"

Tutaj widzimy zmianę id i opisu FlightA, ponieważ parametr przekazany do metody modify faktycznie wskazuje na adres pamięci obiektu flightA (Typ odniesienia).

Teraz jeśli wydrukujemy id i opis instancji flightb otrzymamy,

id = 100
description = "first ever flight of Virgin Airlines"

Tutaj widzimy, że instancja FlightB nie została zmieniona, ponieważ w metodzie modifyFlight2 rzeczywista instancja Flight2 jest przekazywana zamiast referencji (typu wartości).

 8
Author: Manoj Karki,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-05 10:31:57

Odpowiadając na pytanie z perspektywy typów wartości vs typów referencji, z Ten post na blogu Apple wydaje się bardzo prosty:

Użyj typu wartości [np. struct, enum], gdy:

  • porównywanie danych instancji z = = ma sens
  • chcesz, aby kopie miały niezależne państwo
  • Dane będą używane w kodzie w wielu wątkach

Użyj typu odniesienia [np. Klasa], gdy:

  • porównywanie instancji tożsamość z = = = ma sens
  • chcesz utworzyć wspólny, zmienny stan

Jak wspomniano w tym artykule, Klasa bez właściwości do zapisu będzie zachowywać się identycznie ze strukturą, z (dodam) jednym zastrzeżeniem: struktury są najlepsze dla modeli bezpiecznych dla wątków - coraz bardziej nieuchronny wymóg w nowoczesnej architekturze aplikacji.

 4
Author: David James,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-06 13:06:13

Z klasami otrzymujesz dziedziczenie i są przekazywane przez referencję, struktury nie mają dziedziczenia i są przekazywane przez wartość.

Są świetne sesje WWDC na Swift, na to konkretne pytanie dokładnie odpowiadamy w jednej z nich. Upewnij się, że je oglądasz, ponieważ pozwoli Ci to szybciej niż Przewodnik językowy lub iBook.

 3
Author: Joride,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-15 18:36:15

Nie powiedziałbym, że struktury oferują mniejszą funkcjonalność.

Jasne, jaźń jest niezmienna, z wyjątkiem funkcji mutującej, ale to wszystko.

Dziedziczenie działa dobrze, dopóki trzymasz się starego, dobrego pomysłu, że każda klasa powinna być abstrakcyjna lub ostateczna.

Zaimplementuj klasy abstrakcyjne jako protokoły, A klasy końcowe jako struktury.

Dobrą rzeczą w strukturach jest to, że możesz zmienić swoje pola bez tworzenia współdzielonego mutowalnego stanu, ponieważ Kopiuj przy zapisie troszczy się o to:)

Dlatego właściwości / pola w poniższym przykładzie są zmienne, czego nie zrobiłbym w klasach Java, C# lub swift .

Przykładowa struktura dziedziczenia z odrobiną brudnego i prostego użycia na dole w funkcji o nazwie "example":

protocol EventVisitor
{
    func visit(event: TimeEvent)
    func visit(event: StatusEvent)
}

protocol Event
{
    var ts: Int64 { get set }

    func accept(visitor: EventVisitor)
}

struct TimeEvent : Event
{
    var ts: Int64
    var time: Int64

    func accept(visitor: EventVisitor)
    {
        visitor.visit(self)
    }
}

protocol StatusEventVisitor
{
    func visit(event: StatusLostStatusEvent)
    func visit(event: StatusChangedStatusEvent)
}

protocol StatusEvent : Event
{
    var deviceId: Int64 { get set }

    func accept(visitor: StatusEventVisitor)
}

struct StatusLostStatusEvent : StatusEvent
{
    var ts: Int64
    var deviceId: Int64
    var reason: String

    func accept(visitor: EventVisitor)
    {
        visitor.visit(self)
    }

    func accept(visitor: StatusEventVisitor)
    {
        visitor.visit(self)
    }
}

struct StatusChangedStatusEvent : StatusEvent
{
    var ts: Int64
    var deviceId: Int64
    var newStatus: UInt32
    var oldStatus: UInt32

    func accept(visitor: EventVisitor)
    {
        visitor.visit(self)
    }

    func accept(visitor: StatusEventVisitor)
    {
        visitor.visit(self)
    }
}

func readEvent(fd: Int) -> Event
{
    return TimeEvent(ts: 123, time: 56789)
}

func example()
{
    class Visitor : EventVisitor
    {
        var status: UInt32 = 3;

        func visit(event: TimeEvent)
        {
            print("A time event: \(event)")
        }

        func visit(event: StatusEvent)
        {
            print("A status event: \(event)")

            if let change = event as? StatusChangedStatusEvent
            {
                status = change.newStatus
            }
        }
    }

    let visitor = Visitor()

    readEvent(1).accept(visitor)

    print("status: \(visitor.status)")
}
 2
Author: yeoman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-15 09:06:59

W języku Swift wprowadzono nowy wzorzec programowania znany jako programowanie zorientowane na protokół.

Wzór Kreacyjny:

W języku swift, Struct jest typem wartości , które są automatycznie klonowane. Dlatego otrzymujemy wymagane zachowanie, aby zaimplementować wzorzec prototypu za darmo.

Podczas gdy klasy są typem odniesienia, który nie jest automatycznie klonowany podczas przypisywania. Aby zaimplementować wzór prototypu, klasy muszą przyjęcie protokołu {[1] }.


Shallow copy powiela tylko odniesienie, które wskazuje na te obiekty, podczas gdy deep copy powiela odniesienie do obiektu.


Implementacja głębokiej kopii dla każdego typu odniesienia stała się żmudnym zadaniem. Jeśli klasy zawierają kolejny typ referencji, musimy zaimplementować wzór prototypu dla każdej z właściwości referencji. A następnie musimy skopiować cały wykres obiektowy implementując NSCopying protokół.

class Contact{
  var firstName:String
  var lastName:String
  var workAddress:Address // Reference type
}

class Address{
   var street:String
   ...
} 

Używając structs i enums , uprościliśmy nasz kod, ponieważ nie musimy implementować logiki kopiowania.

 2
Author: Balasubramanian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-22 09:53:17

Wiele interfejsów API Cocoa wymaga podklas NSObject, co zmusza do używania klasy. Ale poza tym, możesz użyć następujących przypadków z bloga Swift firmy Apple, aby zdecydować, czy użyć typu wartości struct / enum, czy typu odniesienia do klasy.

Https://developer.apple.com/swift/blog/?id=10

 1
Author: akshay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-17 11:17:16

Jednym z punktów, który nie zwraca uwagi w tych odpowiedziach, jest to, że zmienna przechowująca klasę vs strukturę może być let, jednocześnie zezwalając na zmiany właściwości obiektu, podczas gdy nie można tego zrobić ze strukturą.

Jest to przydatne, jeśli nie chcesz, aby zmienna kiedykolwiek wskazywała na inny obiekt, ale nadal musisz go zmodyfikować, tzn. w przypadku posiadania wielu zmiennych instancji, które chcesz aktualizować jedna po drugiej. Jeśli jest to struktura, musisz zezwolić na reset zmiennej do inny obiekt używa w tym celu var, ponieważ typ wartości stałej w języku Swift prawidłowo pozwala na mutację zerową, podczas gdy typy referencyjne (klasy) nie zachowują się w ten sposób.

 0
Author: johnbakers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-19 12:57:10

Ponieważ struktury są typami wartości i można bardzo łatwo utworzyć pamięć, która przechowuje się w stosie.Struktura może być łatwo dostępna, a po zakończeniu prac jest łatwo odalokowana z pamięci stosu poprzez pop z górnej części stosu. Z drugiej strony klasa jest typem odniesienia, który przechowuje w stercie i zmiany dokonane w jednym obiekcie klasy będą miały wpływ na inny obiekt, ponieważ są one ściśle powiązane i typ odniesienia.Wszyscy członkowie struktury są jawni, podczas gdy wszyscy członkowie klasy są prywatne.

Wadą struktury jest to, że nie może być dziedziczona .

 0
Author: Tapash Mollick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-23 12:35:42
  • Struktura i klasa to typy danych użytkownika

  • Domyślnie struktura jest publiczna, podczas gdy klasa jest prywatna

  • Klasa implementuje zasadę enkapsulacji

  • Obiekty klasy są tworzone w pamięci sterty

  • Klasa jest używana do ponownego użycia, podczas gdy struktura jest używana do grupowania dane w tej samej strukturze

  • Struktury danych nie mogą być inicjowane bezpośrednio, ale mogą be przypisany przez zewnętrzną strukturę

  • Klasy dane mogą być inicjowane bezpośrednio przez parametr less konstruktor i przypisany przez parametryzowany konstruktor

 0
Author: Ridaa Zahra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-13 12:37:25