struktura a klasa w szybkim języku


192

Z książki Apple „Jedną z najważniejszych różnic między strukturami i klasami jest to, że struktury są zawsze kopiowane, gdy są przekazywane w kodzie, ale klasy są przekazywane przez odniesienie”.

Czy ktoś może mi pomóc zrozumieć, co to znaczy? Dla mnie klasy i struktury wydają się takie same.


3
Zobacz rozróżnienie między struct i klasą w .NET: stackoverflow.com/a/13275/19100 , domyślam się, że Swift używa tej samej semantyki.
dalle

23
@jonrsharpe może być dla Ciebie łatwe? czy możesz mi dać odpowiedź, jeśli o tym wiesz
Manish Agrawal

1
Wartość vs odniesienie nie jest pojęciem wyłącznie OOP. To tam w C, jak void my_func(int a)vs void my_func(int &a). To bardzo podstawowe pytanie dotyczące programowania. Czytaj więcej: stackoverflow.com/questions/373419/…
superarts.org

Odpowiedzi:


473

Oto przykład z class. Zwróć uwagę, jak po zmianie nazwy instancja, do której odwołują się obie zmienne, jest aktualizowana. Bobjest teraz Suewszędzie, do Bobktórej kiedykolwiek się odwoływano.

class SomeClass {
    var name: String
    init(name: String) {
        self.name = name
    }
}

var aClass = SomeClass(name: "Bob")
var bClass = aClass // aClass and bClass now reference the same instance!
bClass.name = "Sue"

println(aClass.name) // "Sue"
println(bClass.name) // "Sue"

Teraz structwidzimy, że wartości są kopiowane, a każda zmienna zachowuje swój własny zestaw wartości. Kiedy ustawimy nazwę na Sue, Bobstruktura w aStructnie ulegnie zmianie.

struct SomeStruct {
    var name: String
    init(name: String) {
        self.name = name
    }
}

var aStruct = SomeStruct(name: "Bob")
var bStruct = aStruct // aStruct and bStruct are two structs with the same value!
bStruct.name = "Sue"

println(aStruct.name) // "Bob"
println(bStruct.name) // "Sue"

A więc do reprezentowania stanowej złożonej jednostki, a classjest niesamowite. Ale w przypadku wartości, które są po prostu pomiarem lub kawałkami powiązanych danych, structsensowniej jest, aby można je było łatwo kopiować i obliczać z nimi lub modyfikować wartości bez obawy o skutki uboczne.


„Ale za wartości, które nie są bardziej złożone niż zwykła liczba ...” Dzięki za to Alex
Mike Rapadas

7
@MichaelRapadas Liczby faktycznie strukturami w Swift.
Nikolai Ruhe,

Czy możesz to wyjaśnić, aStruct and bStruct are two structs with the same value!myli mnie to, ponieważ wartości zmiennych wewnątrz struktury są różne.
Julian Król

@ JulianKról że linia aStructi bStructmają identyczne wartości. Oba mają jedno namepole, które jest ustawione "Bob". Ale są to dwie różne struktury. Jest to udowodnione w następnym wierszu, gdy możesz zmienić nazwę jednej z struktur, a druga pozostaje niezmieniona.
Alex Wayne,

Właśnie przegapiłem zadanie. To jasne, dzięki. Może na zewnątrz jest za gorąco :-)
Julian Król

60

Zarówno klasa, jak i struktura mogą:

  • Zdefiniuj właściwości do przechowywania wartości
  • Zdefiniuj metody zapewniające funkcjonalność
  • Być przedłużonym
  • Zgodny z protokołami
  • Zdefiniuj intralizatory
  • Zdefiniuj indeksy, aby zapewnić dostęp do ich zmiennych

Tylko klasa może wykonać:

  • Dziedzictwo
  • Typ odlewania
  • Zdefiniuj deinicjalizatory
  • Zezwalaj na liczenie referencji dla wielu referencji.

32

structsą typami wartości. Oznacza to, że jeśli skopiujesz instancję struktury do innej zmiennej, zostanie ona po prostu skopiowana do zmiennej.

Przykład typu wartości

struct Resolution {
    var width = 2
    var height = 3
}

let hd = Resolution(width: 1920, height: 1080)
var cinema = hd //assigning struct instance  to variable
println("Width of cinema instance is \(cinema.width)")//result is 1920
println("Width of hd instance is \(hd.width)")//result is 1920

cinema.width = 2048

println("Width of cinema instance is \(cinema.width)")//result is 2048
println("Width of hd instance is \(hd.width)")//result is 1920

Klasy są typami referencyjnymi. Oznacza to, że jeśli przypiszesz instancję klasy do zmiennej, będzie ona zawierać tylko odwołanie do instancji, a nie do kopii .


5
+1 dla „Jeśli przypiszesz instancję klasy do innej zmiennej, będzie ona zawierać tylko odwołanie do instancji, a nie do skopiowania”.
Saif,

8

Powyższe odpowiedzi są prawidłowe Mam nadzieję, że moja odpowiedź pomoże komuś, kto nie rozumie powyższych odpowiedzi.

Dobrze w Szybkim Są dwa rodzaje obiektów

  1. Struct
  2. Klasa

Główną różnicą między nimi jest

  • Struktura jest typem wartości
  • Klasa jest typem referencyjnym

Na przykład tutaj kod, aby dobrze zrozumieć.

struct SomeStruct {
var a : Int;

init(_ a : Int) {
    self.a = a
}
}

class SomeClass {
var a: Int;

init(_ a: Int) {
    self.a = a
}

}
var x = 11

var someStruct1 = SomeStruct(x)
var someClass1 = SomeClass(x)

var someStruct2 = someStruct1
var someClass2 = someClass1

someClass1.a = 12
someClass2.a // answer is 12 because it is referencing to class 1     property a

someStruct1.a = 14
someStruct2.a // answer is 11 because it is just copying it not referencing it

To była główna różnica, ale mamy również różnice podrzędne.

Klasa

  1. Należy zadeklarować inicjator (konstruktor)
  2. Ma deinicjalizatory
  3. Może dziedziczyć po innych klasach

Struct

  1. Ma dla ciebie darmowy inicjator, nie musisz deklarować inicjalizatora, jeśli zrobisz darmowy inicjator zostanie zastąpiony przez zadeklarowany inicjator
  2. Nie masz deinicjatora
  3. Nie można dziedziczyć z innych struktur

7

To pytanie wydaje się być zduplikowane, ale niezależnie od tego, odpowiedź na większość przypadków użycia:

  1. Jedną z najważniejszych różnic między strukturami i klasami jest to, że struktury są typami wartości i zawsze są kopiowane, gdy są przekazywane w kodzie, a klasy są typem referencyjnym i są przekazywane przez referencję.

  2. Ponadto klasy mają dziedziczenie, które pozwala jednej klasie na dziedziczenie właściwości innej.

  3. Właściwości konstrukcji są przechowywane na stosie, a instancje klasy są przechowywane na stercie, dlatego czasami stos jest znacznie szybszy niż klasa.

  4. Struct automatycznie inicjuje domyślny inicjator, podczas gdy w Class musimy inicjalizować.

  5. Konstrukcja jest bezpieczna dla wątków lub singleton w dowolnym momencie.

Ponadto, aby podsumować różnicę między strukturami i klasami, konieczne jest zrozumienie różnicy między wartościami a typami referencyjnymi.

  1. Kiedy tworzysz kopię typu wartości, kopiuje ona wszystkie dane z kopiowanej rzeczy do nowej zmiennej. Są to dwie osobne rzeczy, a zmiana jednej nie wpływa na drugą.
  2. Kiedy tworzysz kopię typu odwołania, nowa zmienna odnosi się do tej samej lokalizacji w pamięci, co kopiowana rzecz. Oznacza to, że zmiana jednego spowoduje zmianę drugiego, ponieważ oba odnoszą się do tej samej lokalizacji pamięci. Przykładowy kod poniżej może być traktowany jako odniesienie.

// sampleplayground.playground

  class MyClass {
        var myName: String
        init(myName: String){
            self.myName = myName;
        }
    }

    var myClassExistingName = MyClass(myName: "DILIP")
    var myClassNewName = myClassExistingName
    myClassNewName.myName = "John"


    print("Current Name: ",myClassExistingName.myName)
    print("Modified Name", myClassNewName.myName)

    print("*************************")

    struct myStruct {
        var programmeType: String
        init(programmeType: String){
            self.programmeType = programmeType
        }
    }

    var myStructExistingValue = myStruct(programmeType: "Animation")
    var myStructNewValue = myStructExistingValue
    myStructNewValue.programmeType = "Thriller"

    print("myStructExistingValue: ", myStructExistingValue.programmeType)
    print("myStructNewValue: ", myStructNewValue.programmeType)

Wynik:

Current Name:  John
Modified Name John
*************************
myStructExistingValue:  Animation
myStructNewValue:  Thriller

Cześć Dilip, czy możesz podać przykład dla „Struct jest wątek bezpieczny lub singleton w dowolnym momencie”.? Z góry dziękuję.
Narasimha Nallamsetty

3

Jeśli spojrzysz dalej w podręczniku Apple, zobaczysz tę sekcję: „Struktury i wyliczenia są typami wartości”

W tej sekcji zobaczysz to:

„Niech hd = Rozdzielczość (szerokość: 1920, wysokość: 1080) var cinema = hd Ten przykład deklaruje stałą o nazwie hd i ustawia ją na Rozdzielczość instancja zainicjowana szerokością i wysokością wideo Full HD (1920 pikseli szerokości i 1080 pikseli wysokości).

Następnie deklaruje zmienną o nazwie kino i ustawia ją na bieżącą wartość hd. Ponieważ Resolution jest strukturą, tworzona jest kopia istniejącej instancji, a ta nowa kopia jest przypisywana do kina. Mimo że HD i kino mają teraz tę samą szerokość i wysokość, są to dwa zupełnie różne przypadki za kulisami.

Następnie właściwość width kina zostaje zmieniona na szerokość nieco szerszego standardu 2K stosowanego do cyfrowej projekcji kinowej (szerokość 2048 pikseli i wysokość 1080 pikseli):

Cinema. Width = 2048 Sprawdzanie właściwości width kina pokazuje, że rzeczywiście zmienił się na 2048:

Println („kino jest teraz (kino. Szerokość) szerokość pikseli”) // drukuje ”kino ma teraz szerokość 2048 pikseli Jednak właściwość width oryginalnej instancji hd nadal ma starą wartość 1920:

println („hd wciąż ma szerokość (hd. szerokość) pikseli”) // drukuje „hd wciąż ma szerokość 1920 pikseli”

Gdy kino otrzymało bieżącą wartość hd, wartości zapisane w hd zostały skopiowane do nowej instancji kina. Rezultatem końcowym są dwie całkowicie odrębne instancje, które akurat zawierały te same wartości liczbowe. Ponieważ są to osobne instancje, ustawienie szerokości kina na 2048 nie wpływa na szerokość zapisaną w HD. ”

Fragment: Apple Inc. „Swift Programming Language”. iBooks. https://itun.es/us/jEUH0.l

Jest to największa różnica między strukturami a klasami. Struktury są kopiowane, a klasy są przywoływane.


1

Zwykle (w większości języków programowania) obiekty to bloki danych, które są przechowywane na stercie, a następnie odwołanie (zwykle wskaźnik) do tych bloków zawiera znak a, nameaby uzyskać dostęp do tych bloków danych. Ten mechanizm umożliwia współdzielenie obiektów na stercie poprzez kopiowanie wartości ich referencji (wskaźników). Nie dotyczy to podstawowych typów danych, takich jak liczby całkowite, a to dlatego, że pamięć potrzebna do utworzenia odwołania jest prawie taka sama jak obiekt (w tym przypadku wartość całkowita). Dlatego będą przekazywane jako wartości, a nie jako odniesienie w przypadku dużych obiektów.

Swift używa struct, aby poprawić wydajność nawet w przypadku obiektów String i Array.

Naprawdę dobra lektura tutaj


1

Aby zrozumieć różnicę między Strukturami a Klasami, musimy znać główną różnicę między wartościami a typami odniesienia. Struktury są typami wartości, co oznacza, że ​​każda zmiana na nich po prostu zmodyfikuje tę wartość, Klasy są typami referencyjnymi, a każda zmiana w typie referencyjnym zmodyfikuje wartość przydzieloną w tym miejscu pamięci lub referencji. Na przykład:

Zacznijmy od klasy, ta klasa jest zgodna z Equatable tylko po to, aby móc porównywać instancje, tworzymy instancję o nazwie, pointClassInstanceAa inną o nazwie pointClassInstanceBprzypisujemy klasę A do klasy B, teraz twierdzenie mówi, że są takie same ...

class PointClass: Equatable {
    var x: Double
    var y: Double

    init(x: Double, y: Double) {
        self.x = x
        self.y = y
    }

    static func == (lhs: PointClass, rhs: PointClass) -> Bool {
        return lhs.x == rhs.x && lhs.y == rhs.y
    }
}

var pointClassInstanceA = PointClass(x: 0, y: 0)
var pointClassInstanceB = pointClassInstanceA

assert(pointClassInstanceA==pointClassInstanceB) 

pointClassInstanceB.x = 10
print(pointClassInstanceA.x)
//this prints 10

Ok, co się tutaj stało, dlaczego po prostu zmieniliśmy wartość x pointClassInstanceB, zmieniła się również wartość x pointClassInstanceA? pokazuje to, jak działają typy referencji, kiedy przypisujemy instancję A, jako wartość instancji B, a następnie modyfikujemy X jednego z nich, zmieni to oba X, ponieważ dzielą to samo odwołanie, a to, co się zmieniło, była wartością tego odniesienie.

Zróbmy to samo, ale ze strukturą

struct PointStruct: Equatable {
    var x: Double
    var y: Double

    init(x: Double, y: Double) {
        self.x = x
        self.y = y
    }

    static func == (lhs: PointStruct, rhs: PointStruct) -> Bool {
        return lhs.x == rhs.x && lhs.y == rhs.y
    }
}
var pointStructInstanceA = PointStruct(x: 0, y: 0)
var pointStructInstanceB = pointStructInstanceA

assert(pointStructInstanceA==pointStructInstanceB)
pointStructInstanceB.x = 100
print(pointStructInstanceA.x)
//this will print 0

Mamy zasadniczo taką samą strukturę jak nasza klasa, ale teraz widać, że po wydrukowaniu wartości x pointStructInstanceA w tym przypadku nie uległa ona zmianie, a to dlatego, że typy wartości działają inaczej i każda zmiana w jednym z ich wystąpień będzie „ niezależne ”i nie wpłynie na innych.

Swift sugeruje użycie większej liczby typów wartości i można powiedzieć, że ich biblioteki są oparte na strukturach, aby uniknąć problemów związanych z typami odwołań, takich jak niezamierzona modyfikacja wartości itp. Struktury są sposobem na przejście do Swift. Mam nadzieję, że to pomoże.


1

Oto przykład, który dokładnie pokazuje różnicę między strukturą a klasą.

zrzut ekranu napisanego kodu na placu zabaw
zrzut ekranu napisanego kodu na placu zabaw

struct Radio1{
    var name:String
    //    init(name:String) {
    //        self.name = name
    //    }
}

struct Car1{
    var radio:Radio1?
    var model:String

}

var i1 = Car1(radio: Radio1(name:"murphy"),model:"sedan")
var i2 = i1
//since car instance i1 is a struct and 
//this car has every member as struct ,
//all values are copied into i2

i2.radio?.name //murphy
i2.radio = Radio1(name: "alpha")
i2.radio?.name //alpha

i1.radio?.name //murphy

//since Radio1 was struct , 
//values were copied and thus
// changing name  of instance of Radio1 in i2 
//did not bring change in i1

class Radio2{
    var name:String
    init(name:String) {
        self.name = name
    }
}

struct Car2{
    var radio:Radio2?
    var model:String

}
var i3 = Car2(radio: Radio2(name:"murphy"),model:"sedan")
//var radioInstance = Radio2(name: "murphy")
//var i3 = Car2(radio: radioInstance,model:"sedan")

var i4 = i3
//since i3 is instance of struct
//everything is copied to i4 including reference of instance of Radio2
//because Radio2 is a class



i4.radio?.name //murphy
i4.radio?.name="alpha"
i4.radio?.name //alpha

i3.radio?.name //alpha

//since Radio2 was class, 
//reference was copied and 
//thus changing name of instance 
//of Radio2 in i4 did  bring change in i3 too


//i4.radio?.name
//i4.radio = Radio2(name: "alpha")
//i4.radio?.name
//
//i3.radio?.name

1
1.structure is value type.
   = > when we assign structure variable to other variable or pass as parameter to function, it creates separate/new copy => so that changes made on one variable does not  reflect on another.[We can say like **call by value** concept] 
Example :

    struct DemoStruct 
    { 
        var value: String 
        init(inValue: String) 
        { 
            self.value = inValue 
        } 
    } 


var aStruct = DemoStruct(inValue: "original") 
var bStruct = aStruct // aStruct and bStruct are two structs with the same value! but references to diff location`enter code here`
bStruct.value = "modified" 

print(aStruct.value) // "original" 
print(bStruct.value) // "modified"


2.class is reference type.
 = > when we assign structure variable to other variable or pass as parameter to function, it **does not** creates separate/new copy => so that changes made on one variable does not  reflect on another.[We can say like **call by reference** concept] 
Example:
class DemoClass 
{   
    var value: String 
    init(inValue: String) 
    {
        self.value = inValue 
    } 
} 

var aClass = DemoClass(inName: "original") 
var bClass = aClass // aClass and bClass now reference the same instance! 
bClass.value = "modified" 

print(aClass.value) // "modified" 
print(bClass.value) // "modified"

1

Szybkie typy

Value type jest typem, którego wartość jest kopiowana, gdy jest przypisana do zmiennej lub stałej lub gdy jest przekazana do funkcji

Reference types nie są kopiowane, gdy są przypisane do zmiennej lub stałej lub gdy są przekazywane do funkcji

Typ wartości :
Struct, Enum, Tuple
struct String, struct Array( Set, Dictionary)

  • Po przypisaniu lub przekazaniu tworzona jest value typenowa kopia danych. W rzeczywistości mechanizm copy on write- COWjest używany z pewnymi optymalizacjami, na przykład kopia jest tworzona podczas modyfikowania obiektu
  • Po zmodyfikowaniu wystąpienia ma on tylko efekt lokalny .
  • Pamięci Stos jest używany.

Oznaczenie typu :
Class,Function

  • Po przypisaniu lub przekazać nowe odniesienie do oryginalnej instancji zostanie utworzony (adres instancji jest kopiowany).reference type
  • Po zmodyfikowaniu wystąpienia ma on globalny efekt, ponieważ wystąpienie jest współużytkowane i dostępne dla każdego odwołania do niego wskazującego.
  • Heap pamięci jest używana.

wprowadź opis zdjęcia tutaj

Value typezaleca się używać domyślnie . Największą zaletą Value typejest to, że zwykle sąthread safe

Reference type Plusy:

  • można je odziedziczyć,
  • deinit() może być użyty,
  • porównaj instancje przez odniesienie ===,
  • Objective-Cinteroperacyjność, ponieważ Value Typezostała wprowadzona w Swift.

[Więcej o zmienność]
Wybór między strukturami i klas
Rodzaje
klas i struktur


0

Już dużo jest o tym napisane, chciałbym tam dodać analogię. Mam nadzieję, że po tym nigdy nie będziesz mieć wątpliwości: Podsumowanie: klasy są przekazywane przez referencję, podczas gdy struktury są przekazywane przez wartość.

Załóżmy, że udostępniasz arkusz dokumentu google znajomemu. Teraz, jeśli on coś w tym zmieni, zobaczysz również, że zmiany w twoim dokumencie Google, oznaczają, że twoja kopia również ma wpływ. Zasadniczo jest to „ przekazywane przez odniesienie ”.

Ale załóżmy, że jeśli masz plik .XLS zapisany w twoim komputerze. Dostarczasz ten plik swojemu znajomemu. Teraz, jeśli dokona jakiejkolwiek zmiany w tym pliku, twój plik nie zostanie pomieszany / zmieniony, ponieważ masz własną kopię. To w zasadzie „ przekazane przez wartość ”. Masz już wiele prostych programów, aby sprawdzić tę analogię na szybkich placach zabaw.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.