estructura vs clase en lenguaje rápido


192

Del libro de Apple "Una de las diferencias más importantes entre estructuras y clases es que las estructuras siempre se copian cuando se pasan en su código, pero las clases se pasan por referencia".

¿Alguien puede ayudarme a entender lo que eso significa? Para mí, las clases y las estructuras parecen ser las mismas.


3
Vea la distinción entre estructura y clase en .NET: stackoverflow.com/a/13275/19100 , supongo que Swift usa la misma semántica.
dalle

23
@jonrsharpe podría ser fácil para ti? ¿Me puede dar la respuesta si sabe esto
Manish Agrawal

1
El valor frente a la referencia no es un concepto único de OOP Es allí en C, como void my_func(int a)vs void my_func(int &a). Esta es una cuestión muy fundamental de programación. Leer más: stackoverflow.com/questions/373419/…
superarts.org

Respuestas:


473

Aquí hay un ejemplo con a class. Tenga en cuenta que cuando se cambia el nombre, se actualiza la instancia a la que hacen referencia ambas variables. Bobes ahora Sue, en todas partes que Bobalguna vez se hizo referencia.

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"

Y ahora con un structvemos que los valores se copian y cada variable mantiene su propio conjunto de valores. Cuando establecemos el nombre en Sue, la Bobestructura aStructno cambia.

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"

Entonces, para representar una entidad compleja con estado, a classes increíble. Pero para los valores que son simplemente una medida o bits de datos relacionados, a structtiene más sentido para que pueda copiarlos fácilmente y calcular con ellos o modificar los valores sin temor a los efectos secundarios.


"Pero para valores que no son más complejos que simplemente un número ..." Gracias por esto Alex
Mike Rapadas

77
@MichaelRapadas Los números en realidad son estructuras en Swift.
Nikolai Ruhe

¿Podría aclarar esto? aStruct and bStruct are two structs with the same value!Esto me confunde ya que los valores de las variables dentro de la estructura son diferentes.
Julian Król

@ JulianKról A esa línea aStructy bStructtienen valores idénticos. Ambos tienen un solo namecampo que se establece "Bob". Pero son dos estructuras diferentes. Esto se demuestra en la siguiente línea cuando puede cambiar el nombre de una de las estructuras, y la otra permanece sin cambios.
Alex Wayne

Acabo de perder la tarea. Está claro, gracias. Tal vez hace demasiado calor afuera :-)
Julian Król

60

Tanto la clase como la estructura pueden hacer:

  • Definir propiedades para almacenar valores.
  • Definir métodos para proporcionar funcionalidad.
  • Ser extendido
  • Cumplir con los protocolos
  • Definir intialisers
  • Definir subíndices para proporcionar acceso a sus variables

Solo la clase puede hacer:

  • Herencia
  • Tipo de fundición
  • Definir desinfectantes
  • Permitir el recuento de referencias para múltiples referencias.

32

structson tipos de valor Significa que si copia la instancia de la estructura a otra variable, solo se copia a la variable.

Ejemplo para tipo de valor

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

Las clases son tipos de referencia. Significa que si asigna una instancia de la clase a una variable, contendrá solo la referencia a la instancia y no la copia .


55
+1 para "Si asigna una instancia de la clase a otra variable, contendrá solo la referencia de la instancia, no la copia".
Saif

8

Las respuestas anteriores son correctas. Espero que mi respuesta ayude a alguien que no entiende las respuestas anteriores.

Bien en Swift Hay dos tipos de objetos.

  1. Estructura
  2. Clase

La principal diferencia entre ellos es

  • Struct es tipo de valor
  • La clase es tipo de referencia

Por ejemplo, aquí código para entender bien.

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

Esta fue la principal diferencia, pero también tenemos diferencias secundarias.

Clase

  1. Debe declarar initialiser (constructor)
  2. Tiene desinfectantes
  3. Puede heredar de otras clases.

Estructura

  1. Tiene un iniciador gratuito para usted, no tiene que declarar el inicializador si lo hace, su inicializador declarado lo sobrescribirá.
  2. No tener desinfectante
  3. No se puede heredar de otra estructura

7

Esta pregunta parece estar duplicada, pero independientemente, lo siguiente respondería la mayoría de los casos de uso:

  1. Una de las diferencias más importantes entre estructuras y clases es que las estructuras son tipos de valor y siempre se copian cuando se pasan en su código, y las clases son de tipo de referencia y se pasan por referencia.

  2. Además, las clases tienen herencia que permite que una clase herede las características de otra.

  3. Las propiedades de estructura se almacenan en la pila y las instancias de clase se almacenan en el montón, por lo tanto, a veces la pila es drásticamente más rápida que una clase.

  4. Struct obtiene un inicializador predeterminado automáticamente, mientras que en Class, tenemos que inicializar.

  5. Struct es seguro para subprocesos o singleton en cualquier momento.

Y también, para resumir la diferencia entre estructuras y clases, es necesario comprender la diferencia entre el valor y los tipos de referencia.

  1. Cuando realiza una copia de un tipo de valor, copia todos los datos de lo que está copiando en la nueva variable. Son 2 cosas separadas y cambiar una no afecta a la otra.
  2. Cuando realiza una copia de un tipo de referencia, la nueva variable se refiere a la misma ubicación de memoria que la que está copiando. Esto significa que cambiar uno cambiará el otro ya que ambos se refieren a la misma ubicación de memoria. El código de muestra a continuación podría tomarse como referencia.

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

Salida:

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

Hola Dilip, ¿Puedes dar un ejemplo para "Struct es seguro para subprocesos o singleton en cualquier momento"? Gracias por adelantado.
Narasimha Nallamsetty

3

Si busca más en el manual de Apple, verá esta sección: "Las estructuras y las enumeraciones son tipos de valor"

En esta sección verá esto:

"Let hd = Resolución (ancho: 1920, altura: 1080) var cinema = hd Este ejemplo declara una constante llamada hd y la establece en una Resolución instancia inicializada con el ancho y la altura del video Full HD (1920 píxeles de ancho por 1080 píxeles de alto).

Luego declara una variable llamada cinema y la establece en el valor actual de hd. Como la resolución es una estructura, se realiza una copia de la instancia existente y esta nueva copia se asigna al cine. Aunque hd y cinema ahora tienen el mismo ancho y alto, son dos instancias completamente diferentes detrás de escena.

A continuación, la propiedad de ancho del cine se modifica para que sea el ancho del estándar 2K ligeramente más ancho utilizado para la proyección de cine digital (2048 píxeles de ancho y 1080 píxeles de alto):

Ancho de cine = 2048 La comprobación de la propiedad de ancho del cine muestra que efectivamente ha cambiado para ser 2048:

Println ("cinema es ahora (cinema. Ancho) píxeles de ancho") // imprime "cinema es ahora de 2048 píxeles de ancho Sin embargo, la propiedad de ancho de la instancia de hd original todavía tiene la antigua valor de 1920:

println ("hd sigue siendo (ancho hd) píxeles de ancho") // imprime "hd sigue siendo 1920 píxeles de ancho"

Cuando se le dio al cine el valor actual de hd, los valores almacenados en hd se copiaron en la nueva instancia de cinema. El resultado final son dos instancias completamente separadas, que por casualidad contienen los mismos valores numéricos. Debido a que son instancias separadas, establecer el ancho del cine en 2048 no afecta el ancho almacenado en hd ”.

Extracto de: Apple Inc. "El lenguaje de programación Swift". iBooks https://itun.es/us/jEUH0.l

Esta es la mayor diferencia entre estructuras y clases. Las estructuras se copian y se hace referencia a clases.


1

Por lo general (en la mayoría de los lenguajes de programación), los objetos son bloques de datos que se almacenan en el montón, y luego una referencia (normalmente un puntero) a estos bloques, contiene un nameuso para acceder a estos bloques de datos. Este mecanismo permite compartir objetos en el montón copiando el valor de sus referencias (punteros). Este no es el caso de los tipos de datos básicos, como los enteros, y eso se debe a que la memoria necesaria para crear una referencia es casi la misma que el objeto (en este caso, el valor entero). Por lo tanto, se pasarán como valores, no como referencia en el caso de objetos grandes.

Swift usa struct para mejorar el rendimiento incluso con objetos String y Array.

Una muy buena lectura aquí


1

Para comprender la diferencia entre estructuras y clases, necesitamos conocer la diferencia principal entre el valor y los tipos de referencia. Las estructuras son tipos de valor y eso significa que cada cambio en ellas solo modificará ese valor, las clases son tipos de referencia y cada cambio en un tipo de referencia modificará el valor asignado en ese lugar de memoria o referencia. Por ejemplo:

Comencemos con una clase, esta clase se ajusta a Equatable solo para poder comparar instancias, creamos una instancia llamada pointClassInstanceAy otra llamada pointClassInstanceBasignamos clase A a clase B, ahora la afirmación dice que son lo mismo ...

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, ¿qué pasó aquí por qué si solo cambiamos el valor x de pointsClassInstanceB también cambia el valor x de pointClassInstanceA? bueno, esto muestra cómo funcionan los tipos de referencia, cuando asignamos la instancia A, como un valor de la instancia B y luego modificamos X de uno de ellos, cambiará ambas X porque comparten la misma referencia y lo que cambió fue el valor de esa instancia referencia.

Hagamos lo mismo pero con una estructura

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

Básicamente tenemos la misma estructura que nuestra clase, pero ahora puede ver que cuando imprime el valor x de pointStructInstanceA en este caso no cambió, y esto se debe a que los tipos de valor funcionan de manera diferente y cada cambio en una de sus instancias será " independiente "y no afectará al otro.

Swift sugiere utilizar más tipos de valores y puede darse cuenta de que sus bibliotecas se basan en estructuras para evitar los problemas que traen los tipos de referencia, como modificar involuntariamente un valor, etc. Las estructuras son el camino a seguir en Swift. Espero eso ayude.


1

Aquí hay un ejemplo que muestra la diferencia entre struct y class con precisión.

captura de pantalla del código escrito en el patio de recreo
captura de pantalla del código escrito en el patio de recreo

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

Tipos rápidos

Value type es un tipo cuyo valor se copia cuando se asigna a una variable o constante, o cuando se pasa a una función

Reference types no se copian cuando se asignan a una variable o constante, o cuando se pasan a una función

Tipo de valor :
Struct, Enum,Tuple
struct String , struct Array(Set , Dictionary)

  • Cuando asignas o pasas value type una nueva copia de datos se crea. En realidad, el mecanismo copy on write- COWse usa con algunas optimizaciones, por ejemplo, la copia se crea cuando se modifica el objeto
  • Cuando usted modificas una instancia, solo tiene efecto local .
  • los utiliza la memoria de pila .

Tipo de referencia :
Class ,Function

  • Cuando asignas o pasas reference type una nueva referencia a la instancia original, se creará (se copia la dirección de la instancia).
  • Cuando modificas una instancia, tiene un efecto global porque la instancia es compartida y accesible por cualquier referencia que la señale.
  • Se utiliza la memoria de almacenamiento dinámico .

ingrese la descripción de la imagen aquí

Value typese recomienda usar por defecto . La mayor ventaja deValue type es que generalmente sonthread safe

Reference type Pros:

  • pueden ser heredados
  • deinit() puede ser usado,
  • comparar instancias por referencia ===,
  • Objective-Cinteroperabilidad porque Value Typese introdujo en Swift.

[Más sobre mutabilidad]
Elección entre estructuras y clases
Tipos
Clases y estructuras


0

Ya hay mucho escrito sobre esto, me gustaría agregar una analogía allí. Espero que nunca tenga dudas en mente después de esto: Conclusión: las clases se pasan por referencia mientras que las estructuras se pasan por valor.

Supongamos que está compartiendo una hoja de documentos de Google con su amigo. Ahora, si cambia algo en eso, también verá que los cambios en su documento de Google, significa que su copia también se ve afectada. Eso es básicamente " aprobado por referencia ".

Pero suponga, si tiene un archivo .XLS guardado en su máquina. Proporcionas ese archivo para darle a tu amigo. Ahora, si está haciendo algún cambio en ese archivo, su archivo no se verá afectado / afectado porque tiene su propia copia. Eso es básicamente " pasado por valor ". Ya tiene varios programas simples para verificar esta analogía en áreas de juego rápidas.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.