Struktur gegen Klasse in schneller Sprache

192

Aus dem Apple-Buch "Einer der wichtigsten Unterschiede zwischen Strukturen und Klassen besteht darin, dass Strukturen immer kopiert werden, wenn sie in Ihrem Code herumgereicht werden, Klassen jedoch als Referenz übergeben werden."

Kann mir jemand helfen zu verstehen, was das bedeutet? Klassen und Strukturen scheinen mir gleich zu sein.

Manish Agrawal
quelle
3
Siehe Unterscheidung zwischen Struktur und Klasse in .NET: stackoverflow.com/a/13275/19100 . Ich vermute , dass Swift dieselbe Semantik verwendet.
Dalle
23
@ Jonrsharpe könnte für Sie einfach sein? Kannst du mir die Antwort geben, wenn du das weißt
?
1
Wert gegen Referenz ist kein OOP-Konzept. Es ist dort in C, wie void my_func(int a)vs void my_func(int &a). Dies ist eine sehr grundlegende Frage der Programmierung. Lesen Sie mehr: stackoverflow.com/questions/373419/…
superarts.org

Antworten:

473

Hier ist ein Beispiel mit einem class. Beachten Sie, dass beim Ändern des Namens die Instanz, auf die beide Variablen verweisen, aktualisiert wird. Bobist jetzt Sueüberall, wo Bobjemals verwiesen wurde.

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"

Und jetzt mit a sehen structwir, dass die Werte kopiert werden und jede Variable ihre eigenen Werte behält. Wenn wir den Namen auf setzen Sue, wird die BobStruktur in aStructnicht geändert.

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"

Für die Darstellung einer komplexen staatlichen Einheit ist a classalso fantastisch. Für Werte, die lediglich eine Messung oder Teile verwandter Daten sind, structist a jedoch sinnvoller, damit Sie sie einfach kopieren und damit berechnen oder die Werte ändern können, ohne Nebenwirkungen befürchten zu müssen.

Alex Wayne
quelle
"Aber für Werte, die nicht komplexer sind als nur eine Zahl ..." Danke für diesen Alex
Mike Rapadas
7
@MichaelRapadas Zahlen tatsächlich sind structs in Swift.
Nikolai Ruhe
Könnten Sie das klarstellen, das aStruct and bStruct are two structs with the same value!verwirrt mich, da die Werte der Variablen innerhalb der Struktur unterschiedlich sind.
Julian Król
@ JulianKról A diese Zeile aStructund bStructhaben identische Werte. Sie haben beide ein einziges nameFeld, auf das gesetzt wird "Bob". Aber es sind zwei verschiedene Strukturen. Dies wird in der nächsten Zeile bewiesen, wenn Sie den Namen einer der Strukturen ändern können und die andere unverändert bleibt.
Alex Wayne
Habe gerade die Aufgabe verpasst. Es ist klar, danke. Vielleicht ist es draußen zu heiß :-)
Julian Król
60

Sowohl Klasse als auch Struktur können:

  • Definieren Sie Eigenschaften zum Speichern von Werten
  • Definieren Sie Methoden zur Bereitstellung von Funktionen
  • Erweitert
  • Protokolle einhalten
  • Definieren Sie Intialisierer
  • Definieren Sie Indizes, um Zugriff auf ihre Variablen zu erhalten

Nur die Klasse kann:

  • Erbe
  • Typ Casting
  • Definieren Sie Deinitialisierer
  • Referenzzählung für mehrere Referenzen zulassen.
Durul Dalkanat
quelle
32

structsind Werttypen. Wenn Sie die Instanz der Struktur in eine andere Variable kopieren, wird sie nur in die Variable kopiert.

Beispiel für Werttyp

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

Klassen sind Referenztypen. Wenn Sie einer Variablen eine Instanz der Klasse zuweisen, enthält diese nur den Verweis auf die Instanz und nicht die Kopie .

ashok vadivelu
quelle
5
+1 für "Wenn Sie eine Instanz der Klasse einer anderen Variablen zuweisen, enthält sie nur die Referenz der Instanz, die nicht kopiert wird."
Saif
8

Die obigen Antworten sind korrekt. Ich hoffe, meine Antwort hilft jemandem, der die obigen Antworten nicht versteht.

Nun, in Swift gibt es zwei Arten von Objekten

  1. Struct
  2. Klasse

Hauptunterschied zwischen ihnen ist

  • Struct ist Wert Typ
  • Klasse ist Referenztyp

Zum Beispiel hier Code, um gut zu verstehen.

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

Dies war der Hauptunterschied, aber wir haben auch Unterunterschiede.

Klasse

  1. Muss Initialisierer (Konstruktor) deklarieren
  2. Hat deinitialisers
  3. Kann von anderen Klassen erben

Struct

  1. Es hat einen kostenlosen Initialisierer für Sie. Sie müssen den Initialisierer nicht deklarieren, wenn Sie einen kostenlosen Initialisierer verwenden, der von Ihrem deklarierten Initialisierer überschrieben wird
  2. Ich habe keinen Deinitialisierer
  3. Kann nicht von einer anderen Struktur erben
Dara
quelle
7

Diese Frage scheint doppelt zu sein, aber unabhängig davon würde Folgendes den größten Teil des Anwendungsfalls beantworten:

  1. Einer der wichtigsten Unterschiede zwischen Strukturen und Klassen besteht darin, dass Strukturen Werttypen sind und immer kopiert werden, wenn sie in Ihrem Code weitergegeben werden. Klassen sind Referenztypen und werden als Referenz übergeben.

  2. Klassen haben auch Vererbung, die es einer Klasse ermöglicht, die Eigenschaften einer anderen zu erben.

  3. Struktureigenschaften werden auf dem Stapel gespeichert, und Klasseninstanzen werden auf dem Heap gespeichert. Daher ist der Stapel manchmal drastisch schneller als eine Klasse.

  4. Struct erhält automatisch einen Standardinitialisierer, während wir in Class initialisieren müssen.

  5. Struct ist zu jedem Zeitpunkt threadsicher oder singleton.

Um den Unterschied zwischen Strukturen und Klassen zusammenzufassen, ist es außerdem erforderlich, den Unterschied zwischen Wert- und Referenztypen zu verstehen.

  1. Wenn Sie eine Kopie eines Wertetyps erstellen, werden alle Daten von dem Objekt, das Sie kopieren, in die neue Variable kopiert. Sie sind zwei getrennte Dinge und das Ändern eines wirkt sich nicht auf das andere aus.
  2. Wenn Sie eine Kopie eines Referenztyps erstellen, bezieht sich die neue Variable auf denselben Speicherort wie das zu kopierende Objekt. Dies bedeutet, dass das Ändern des einen den anderen ändert, da sich beide auf denselben Speicherort beziehen. Der folgende Beispielcode könnte als Referenz dienen.

// 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)

Ausgabe:

Current Name:  John
Modified Name John
*************************
myStructExistingValue:  Animation
myStructNewValue:  Thriller
DILIP KOSURI
quelle
Hallo Dilip, können Sie ein Beispiel für "Struktur ist zu jedem Zeitpunkt threadsicher oder Singleton?" Geben. Danke im Voraus.
Narasimha Nallamsetty
3

Wenn Sie weiter im Apple-Handbuch nachsehen, sehen Sie diesen Abschnitt: „Strukturen und Aufzählungen sind Werttypen“.

In diesem Abschnitt sehen Sie Folgendes:

“Let hd = Auflösung (Breite: 1920, Höhe: 1080) varinema = hd In diesem Beispiel wird eine Konstante namens hd deklariert und auf eine Auflösung festgelegt Instanz, die mit der Breite und Höhe von Full-HD-Videos initialisiert wurde (1920 Pixel breit und 1080 Pixel hoch).

Anschließend wird eine Variable namens Kino deklariert und auf den aktuellen Wert von hd gesetzt. Da Resolution eine Struktur ist, wird eine Kopie der vorhandenen Instanz erstellt und diese neue Kopie dem Kino zugewiesen. Obwohl HD und Kino jetzt die gleiche Breite und Höhe haben, sind sie hinter den Kulissen zwei völlig unterschiedliche Beispiele.

Als nächstes wird die Breiteigenschaft des Kinos geändert, um die Breite des etwas breiteren 2K-Standards zu sein, der für die digitale Kinoprojektion verwendet wird (2048 Pixel breit und 1080 Pixel hoch):

Kino. Width = 2048 Die Überprüfung der width-Eigenschaft des Kinos zeigt, dass es sich tatsächlich in 2048 geändert hat:

Println ("Kino ist jetzt (Kino. Breite) Pixel breit") // druckt "Kino ist jetzt 2048 Pixel breit" Die width-Eigenschaft der ursprünglichen HD-Instanz hat jedoch immer noch die alte Wert von 1920:

println ("hd ist immer noch (hd. Breite) Pixel breit") // druckt "hd ist immer noch 1920 Pixel breit"

Wenn dem Kino der aktuelle Wert von hd zugewiesen wurde, wurden die in hd gespeicherten Werte in die neue Kinoinstanz kopiert. Das Endergebnis sind zwei völlig getrennte Instanzen, die zufällig dieselben numerischen Werte enthielten. Da es sich um separate Instanzen handelt, wirkt sich das Festlegen der Breite des Kinos auf 2048 nicht auf die in HD gespeicherte Breite aus. “

Auszug aus: Apple Inc. "Die schnelle Programmiersprache". iBooks. https://itun.es/us/jEUH0.l

Dies ist der größte Unterschied zwischen Strukturen und Klassen. Strukturen werden kopiert und Klassen referenziert.

Stuart Casarotto
quelle
1

Normalerweise (in den meisten Programmiersprachen) sind Objekte Datenblöcke, die auf einem Heap gespeichert sind, und dann enthält eine Referenz (normalerweise ein Zeiger) auf diese Blöcke eine nameVerwendung, um auf diese Datenblöcke zuzugreifen. Dieser Mechanismus ermöglicht die Freigabe von Objekten im Heap, indem der Wert ihrer Referenzen (Zeiger) kopiert wird. Dies ist bei grundlegenden Datentypen wie Integer nicht der Fall, und das liegt daran, dass der zum Erstellen einer Referenz erforderliche Speicher fast dem Objekt entspricht (in diesem Fall ein ganzzahliger Wert). Daher werden sie bei großen Objekten als Werte und nicht als Referenz übergeben.

Swift verwendet struct, um die Leistung auch bei String- und Array-Objekten zu verbessern.

Eine wirklich gute Lektüre hier

William Kinaan
quelle
1

Um den Unterschied zwischen Strukturen und Klassen zu verstehen, müssen wir den Hauptunterschied zwischen Wert- und Referenztypen kennen. Strukturen sind Werttypen, und das bedeutet, dass jede Änderung an ihnen nur diesen Wert ändert. Klassen sind Referenztypen, und jede Änderung an einem Referenztyp ändert den an diesem Speicherort oder dieser Referenz zugewiesenen Wert. Beispielsweise:

Beginnen wir mit einer Klasse. Diese Klasse entspricht Equatable, um Instanzen vergleichen zu können. Wir erstellen eine Instanz mit dem Namen pointClassInstanceAund andere mit dem Namen pointClassInstanceBKlasse A weisen Klasse B zu. Jetzt heißt es in der Behauptung, dass sie gleich sind.

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, was ist hier passiert, warum, wenn wir nur den x-Wert von pointsClassInstanceB geändert haben, hat sich auch der x-Wert von pointClassInstanceA geändert? Nun, dies zeigt, wie Referenztypen funktionieren, wenn wir die Instanz A als Wert von Instanz B zuweisen und dann X von einer von ihnen ändern, werden beide X geändert, da sie dieselbe Referenz haben und was sich geändert hat, war der Wert davon Referenz.

Machen wir dasselbe, aber mit einer 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

Wir haben im Grunde die gleiche Struktur wie unsere Klasse, aber jetzt können Sie sehen, dass sich der x-Wert von pointStructInstanceA in diesem Fall nicht geändert hat. Dies liegt daran, dass Werttypen anders funktionieren und jede Änderung an einer ihrer Instanzen " unabhängig "und wird den anderen nicht beeinflussen.

Swift schlägt vor, mehr Werttypen zu verwenden, und Sie können feststellen, dass ihre Bibliotheken auf Strukturen basieren, um die Probleme zu vermeiden, die Referenztypen mit sich bringen, z. B. das unbeabsichtigte Ändern eines Werts usw. Strukturen sind der richtige Weg für Swift. Ich hoffe es hilft.

James Rochabrun
quelle
1

Hier ist ein Beispiel, das den Unterschied zwischen Struktur und Klasse genau zeigt.

Screenshot des geschriebenen Codes auf dem Spielplatz
Screenshot des geschriebenen Codes auf dem Spielplatz

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
rahul verma
quelle
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"
Sudhir Bhagat
quelle
1

Schnelle Typen

Value type ist ein Typ, dessen Wert kopiert wird, wenn er einer Variablen oder Konstante zugewiesen oder an eine Funktion übergeben wird

Reference types werden nicht kopiert, wenn sie einer Variablen oder Konstante zugewiesen sind oder wenn sie an eine Funktion übergeben werden

Wert Typ :
Struct, Enum, Tuple
struct String, struct Array( Set, Dictionary)

  • Wenn Sie eine neue Kopie der Daten zuweisen oder übergeben, wird diese erstellt. Tatsächlich wird der Mechanismus - bei einigen Optimierungen verwendet, z. B. wird die Kopie erstellt, wenn das Objekt geändert wirdvalue typecopy on writeCOW
  • Wenn Sie eine Instanz ändern , hat dies nur lokale Auswirkungen.
  • Der Stapelspeicher wird verwendet.

Referenz Typ :
Class,Function

  • Wenn Sie reference typeeinen neuen Verweis auf die ursprüngliche Instanz zuweisen oder übergeben, wird dieser erstellt (die Adresse der Instanz wird kopiert).
  • Wenn Sie eine Instanz ändern , hat dies einen globalen Effekt, da die Instanz von jeder Referenz, die darauf verweist, gemeinsam genutzt wird und auf die zugegriffen werden kann.
  • Der Heapspeicher wird verwendet.

Geben Sie hier die Bildbeschreibung ein

Value typewird empfohlen, standardmäßig zu verwenden . Der größte Vorteil Value typeist, dass sie normalerweise sindthread safe

Reference type Vorteile:

  • sie können vererbt werden,
  • deinit() kann verwendet werden,
  • Instanzen anhand von Referenzen vergleichen ===,
  • Objective-CInteroperabilität, weil Value Typein Swift eingeführt wurde.

[Weitere Informationen zur Veränderlichkeit]
Auswahl zwischen Strukturen und
Klassentypen
Klassen und Strukturen

yoAlex5
quelle
0

Heute ist viel darüber geschrieben, ich möchte dort eine Analogie hinzufügen. Ich hoffe, Sie werden danach nie Zweifel haben: Fazit : Klassen werden als Referenz übergeben, während Strukturen als Wert übergeben werden.

Angenommen, Sie teilen ein Google Doc Sheet mit Ihrem Freund. Wenn er daran etwas ändert, werden Sie auch sehen, dass Änderungen an Ihrem Google-Dokument bedeuten, dass Ihre Kopie ebenfalls betroffen ist. Das ist im Grunde " als Referenz übergeben ".

Angenommen, Sie haben eine .XLS-Datei auf Ihrem Computer gespeichert. Sie geben diese Datei an Ihren Freund weiter. Wenn er nun Änderungen an dieser Datei vornimmt, wird Ihre Datei nicht durcheinander gebracht, da Sie über eine eigene Kopie verfügen. Das ist im Grunde " von Wert übergeben ". Sie haben bereits mehrere einfache Programme, um diese Analogie auf schnellen Spielplätzen zu überprüfen.

ASP
quelle