structure vs classe en langage rapide

192

Tiré du livre Apple "L'une des différences les plus importantes entre les structures et les classes est que les structures sont toujours copiées lorsqu'elles sont transmises dans votre code, mais les classes sont passées par référence."

Quelqu'un peut-il m'aider à comprendre ce que cela signifie? Pour moi, les classes et les structures semblent être les mêmes.

Manish Agrawal
la source
3
Voir la distinction entre struct et class dans .NET: stackoverflow.com/a/13275/19100 , je suppose que Swift utilise la même sémantique.
dalle le
23
@jonrsharpe pourrait être facile pour vous? pouvez-vous me donner la réponse si vous savez ceci
Manish Agrawal
1
La valeur par rapport à la référence n'est pas uniquement un concept de POO. Il est là en C, comme void my_func(int a)vs void my_func(int &a). C'est une question de programmation très fondamentale. En savoir plus: stackoverflow.com/questions/373419/…
superarts.org

Réponses:

473

Voici un exemple avec un class. Notez que lorsque le nom est modifié, l'instance référencée par les deux variables est mise à jour. Bobest maintenant Sue, partout qui Boba jamais été référencé.

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"

Et maintenant, avec a, structnous voyons que les valeurs sont copiées et que chaque variable conserve son propre ensemble de valeurs. Lorsque nous définissons le nom sur Sue, la Bobstructure in aStructn'est pas modifiée.

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"

Donc, pour représenter une entité complexe avec état, a classest génial. Mais pour les valeurs qui sont simplement une mesure ou des bits de données associées, a structest plus logique afin que vous puissiez facilement les copier et les calculer avec elles ou modifier les valeurs sans craindre d'effets secondaires.

Alex Wayne
la source
"Mais pour des valeurs qui ne sont pas plus complexes qu'un simple nombre ..." Merci pour cet Alex
Mike Rapadas
7
@MichaelRapadas Les nombres sont en fait des structures dans Swift.
Nikolai Ruhe
Pourriez-vous clarifier cela, aStruct and bStruct are two structs with the same value!cela me trouble car les valeurs des variables à l'intérieur de la structure sont différentes.
Julian Król du
@ JulianKról A cette ligne aStructet bStructont des valeurs identiques. Ils ont tous deux un seul namechamp qui est défini sur "Bob". Mais ce sont deux structures différentes. Cela est prouvé sur la ligne suivante lorsque vous pouvez changer le nom de l'une des structures et que l'autre reste inchangée.
Alex Wayne
Je viens de manquer la mission. C'est clair, merci. Peut-être qu'il fait trop chaud dehors :-)
Julian Król
60

La classe et la structure peuvent faire:

  • Définir les propriétés pour stocker les valeurs
  • Définir des méthodes pour fournir des fonctionnalités
  • Être étendu
  • Conforme aux protocoles
  • Définir les intialiseurs
  • Définir des indices pour donner accès à leurs variables

Seule la classe peut faire:

  • Héritage
  • Type de moulage
  • Définir les déinitialiseurs
  • Autoriser le comptage de références pour plusieurs références.
Durul Dalkanat
la source
32

structsont des types de valeur. Cela signifie que si vous copiez l'instance de la structure dans une autre variable, elle est simplement copiée dans la variable.

Exemple de type de valeur

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

Les classes sont des types de référence. Cela signifie que si vous affectez une instance de la classe à une variable, elle ne contiendra que la référence à l'instance et non la copie .

ashok vadivelu
la source
5
+1 pour "Si vous assignez une instance de la classe à une autre variable, elle ne contiendra que la référence de l'instance et non la copie."
Saif
8

Les réponses ci-dessus sont correctes J'espère que ma réponse aidera quelqu'un qui ne comprend pas les réponses ci-dessus.

Eh bien dans Swift Il existe deux types d'objets

  1. Struct
  2. Classe

La principale différence entre eux est

  • Struct est le type de valeur
  • La classe est le type de référence

Par exemple ici code pour bien comprendre.

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

C'était la principale différence, mais nous avons également des sous-différences.

Classe

  1. Doit déclarer l'initialiseur (constructeur)
  2. Contient des déinitialiseurs
  3. Peut hériter d'autres classes

Struct

  1. Il a un initialiseur gratuit pour vous, vous n'avez pas à déclarer l'initaliseur si vous le faites, l'initialiseur gratuit sera écrasé par votre initialiseur déclaré
  2. Je n'ai pas de désinitialiseur
  3. Impossible d'hériter d'une autre structure
dara
la source
7

Cette question semble être en double mais peu importe, ce qui suit répondrait à la plupart des cas d'utilisation:

  1. L'une des différences les plus importantes entre les structures et les classes est que les structures sont des types valeur et sont toujours copiées lorsqu'elles sont transmises dans votre code, et que les classes sont de type référence et sont passées par référence.

  2. En outre, les classes ont l'héritage qui permet à une classe d'hériter des caractéristiques d'une autre.

  3. Les propriétés Struct sont stockées sur la pile et les instances de classe sont stockées sur le tas, par conséquent, la pile est parfois considérablement plus rapide qu'une classe.

  4. Struct obtient automatiquement un initialiseur par défaut alors qu'en Class, nous devons initialiser.

  5. Struct est thread-safe ou singleton à tout moment.

Et aussi, pour résumer la différence entre les structures et les classes, il est nécessaire de comprendre la différence entre les types valeur et référence.

  1. Lorsque vous faites une copie d'un type valeur, il copie toutes les données de l'élément que vous copiez dans la nouvelle variable. Ce sont deux choses distinctes et changer l'une n'affecte pas l'autre.
  2. Lorsque vous effectuez une copie d'un type référence, la nouvelle variable fait référence au même emplacement mémoire que l'objet que vous copiez. Cela signifie que changer l'un changera l'autre car ils se réfèrent tous deux au même emplacement mémoire. L'exemple de code ci-dessous peut être pris comme référence.

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

Production:

Current Name:  John
Modified Name John
*************************
myStructExistingValue:  Animation
myStructNewValue:  Thriller
DILIP KOSURI
la source
Salut Dilip, Pouvez-vous donner un exemple pour "Struct est thread-safe ou singleton à tout moment." ?. Merci d'avance.
Narasimha Nallamsetty
3

Si vous regardez plus loin dans le manuel Apple, vous verrez cette section: "Les structures et les énumérations sont des types de valeur"

Dans cette section, vous verrez ceci:

"Let hd = Resolution (width: 1920, height: 1080) var cinema = hd Cet exemple déclare une constante appelée hd et la définit sur une résolution instance initialisée avec la largeur et la hauteur de la vidéo Full HD (1920 pixels de large sur 1080 pixels de haut).

Il déclare ensuite une variable appelée cinema et la définit sur la valeur actuelle de hd. La résolution étant une structure, une copie de l'instance existante est créée et cette nouvelle copie est affectée au cinéma. Même si la HD et le cinéma ont maintenant la même largeur et la même hauteur, ce sont deux instances complètement différentes dans les coulisses.

Ensuite, la propriété width du cinéma est modifiée pour être la largeur de la norme 2K légèrement plus large utilisée pour la projection de cinéma numérique (2048 pixels de large et 1080 pixels de haut):

Cinema. Width = 2048 La vérification de la propriété width du cinema montre qu'elle a bien changé pour être 2048:

Println ("le cinéma a maintenant une largeur de (cinéma. Largeur) pixels") // imprime "le cinéma a maintenant une largeur de 2048 pixels. Cependant, la propriété width de l'instance hd d'origine a toujours l'ancienne valeur de 1920:

println ("hd est toujours large (largeur hd.) pixels") // imprime "hd est toujours large de 1920 pixels"

Lorsque le cinéma a reçu la valeur actuelle de hd, les valeurs stockées dans hd ont été copiées dans la nouvelle instance de cinéma. Le résultat final est deux instances complètement distinctes, qui contenaient simplement les mêmes valeurs numériques. Comme il s'agit d'instances distinctes, définir la largeur du cinéma sur 2 048 n'affecte pas la largeur stockée en HD.

Extrait de: Apple Inc. «The Swift Programming Language». iBooks. https://itun.es/us/jEUH0.l

C'est la plus grande différence entre les structures et les classes. Les structures sont copiées et les classes sont référencées.

Stuart Casarotto
la source
1

Habituellement (dans la plupart des langages de programmation), les objets sont des blocs de données qui sont stockés sur le tas, puis une référence (normalement un pointeur) à ces blocs, contient un name est utilisé pour accéder à ces blocs de données. Ce mécanisme permet de partager des objets dans le tas en copiant la valeur de leurs références (pointeurs). Ce n'est pas le cas des types de données de base tels que les entiers, et c'est parce que la mémoire nécessaire pour créer une référence est presque la même que l'objet (dans ce cas, une valeur entière). Ainsi, ils seront passés en tant que valeurs et non en tant que référence dans le cas d'objets volumineux.

Swift utilise struct afin d'améliorer les performances même avec des objets String et Array.

Une très bonne lecture ici

William Kinaan
la source
1

Afin de comprendre la différence entre les structures et les classes, nous devons connaître la principale différence entre les types valeur et référence. Les structures sont des types de valeur et cela signifie que chaque changement sur eux modifiera simplement cette valeur, les classes sont des types de référence et chaque changement dans un type de référence modifiera la valeur allouée à cet endroit de mémoire ou de référence. Par exemple:

Commençons par une classe, cette classe est conforme à Equatable juste pour pouvoir comparer des instances, nous créons une instance appelée pointClassInstanceAet une autre appelée pointClassInstanceBnous assignons la classe A à la classe B, maintenant l'assertion dit qu'elles sont les mêmes ...

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, que s'est-il passé ici pourquoi si nous avons simplement changé la valeur x de pointsClassInstanceB, cela a également changé la valeur x de pointClassInstanceA? Eh bien, cela montre comment les types de référence fonctionnent, lorsque nous affectons l'instance A, en tant que valeur de l'instance B, puis nous modifions X de l'un d'entre eux, cela changera les deux X car ils partagent la même référence et ce qui a changé était la valeur de cela référence.

Faisons la même chose mais avec une structure

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

Nous avons fondamentalement la même structure que notre classe, mais maintenant vous pouvez voir que lorsque vous imprimez la valeur x de pointStructInstanceA, ce cas n'a pas changé, et c'est parce que les types de valeur fonctionnent différemment et que chaque changement sur l'une de leurs instances sera " indépendant "et n'affectera pas l'autre.

Swift suggère d'utiliser plus de types de valeur et vous pouvez dire que leurs bibliothèques sont basées sur des structures pour éviter les problèmes que les types de référence apportent, comme modifier involontairement une valeur, etc. Les structures sont la voie à suivre sur Swift. J'espère que ça aide.

James Rochabrun
la source
1

Voici un exemple qui montre précisément la différence entre struct et class.

capture d'écran du code écrit dans l'aire de jeux
capture d'écran du code écrit dans l'aire de jeux

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
la source
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
la source
1

Types Swift

Value type est un type dont la valeur est copiée lorsqu'elle est affectée à une variable ou constante, ou lorsqu'elle est passée à une fonction

Reference types ne sont pas copiés lorsqu'ils sont affectés à une variable ou une constante, ou lorsqu'ils sont passés à une fonction

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

  • Lorsque vous attribuez ou transmettez value type une nouvelle copie des données est créée. En fait, le mécanisme copy on write- COWest utilisé avec certaines optimisations, par exemple la copie est créée lorsque l'objet est modifié
  • Lorsque vous modifiez une instance, cela n'a qu'un effet local .
  • La mémoire de pile est utilisée.

Type de référence :
Class,Function

  • Lorsque vous attribuez ou passez reference typeune nouvelle référence à l'instance d'origine sera créée (l'adresse de l'instance est copiée).
  • Lorsque vous modifiez une instance, elle a un effet global car l'instance est partagée et accessible par toute référence qui pointe dessus.
  • La mémoire de tas est utilisée.

entrez la description de l'image ici

Value typeest recommandé d'utiliser par défaut . Le plus grand avantage Value typeest qu'ils sont généralementthread safe

Reference type Avantages:

  • ils peuvent être hérités,
  • deinit() peut être utilisé,
  • comparer les instances par référence ===,
  • Objective-Cinteropérabilité car a Value Typeété introduit dans Swift.

[let vs var, class vs struct]
Choix entre les structures et les classes
Types
Classes et structures

yoAlex5
la source
0

Bien qu'il y ait beaucoup d'écrits à ce sujet, je voudrais ajouter une analogie. J'espère que vous n'aurez plus jamais de doute à l'esprit après ceci: Conclusion: les classes sont passées par référence alors que les structures sont passées par valeur.

Supposons que vous partagiez une feuille de documentation google avec votre ami. Maintenant, s'il change quoi que ce soit à cela, vous verrez également que les modifications apportées à votre document google signifient que votre copie est également affectée. C'est fondamentalement " passé par référence ".

Mais supposons que si vous avez un fichier .XLS enregistré sur votre machine. Vous fournissez ce fichier à votre ami. Maintenant, s'il apporte des modifications à ce fichier, votre fichier ne sera pas perturbé / affecté parce que vous avez votre propre copie. C'est fondamentalement " passé par valeur ". Vous disposez déjà de plusieurs programmes simples pour vérifier cette analogie dans les terrains de jeux rapides.

ASPIC
la source