estrutura vs classe em linguagem rápida


192

Do livro da Apple "Uma das diferenças mais importantes entre estruturas e classes é que as estruturas são sempre copiadas quando transmitidas em seu código, mas as classes são transmitidas por referência".

Alguém pode me ajudar a entender o que isso significa? Para mim, classes e estruturas parecem ser as mesmas.


3
Veja a distinção entre struct e classe no .NET: stackoverflow.com/a/13275/19100 , acho que o Swift usa a mesma semântica.
dalle

23
@jonrsharpe pode ser fácil para você? você pode me deu a resposta se você sabe disso
Manish Agrawal

1
Valor vs referência não é apenas um conceito de POO. É lá em C, como void my_func(int a)vs void my_func(int &a). Esta é uma questão muito fundamental de programação. Leia mais: stackoverflow.com/questions/373419/…
superarts.org 02/02

Respostas:


473

Aqui está um exemplo com a class. Observe como quando o nome é alterado, a instância referenciada pelas duas variáveis ​​é atualizada. Bobestá agora Sue, em todo lugar que Bobjá foi referenciado.

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"

E agora, com a struct, vemos que os valores são copiados e cada variável mantém seu próprio conjunto de valores. Quando definimos o nome como Sue, a Bobestrutura aStructnão é alterada.

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"

Portanto, para representar uma entidade complexa com estado, a classé impressionante. Porém, para valores que são simplesmente uma medida ou bits de dados relacionados, structfaz mais sentido que você possa copiá-los facilmente e calculá-los com eles ou modificar os valores sem medo de efeitos colaterais.


"Mas por valores que não são mais complexos do que simplesmente um número ..." Obrigado por isso Alex
Mike Rapadas 29/08/14

7
@MichaelRapadas Os números são realmente estruturas no Swift.
Nikolai Ruhe 16/09

Você poderia esclarecer isso, aStruct and bStruct are two structs with the same value!isso me confunde, pois os valores das variáveis ​​dentro da estrutura são diferentes.
Julian Król

@ JulianKról Uma linha aStructe bStructvalores idênticos. Ambos têm um único namecampo que é definido como "Bob". Mas são duas estruturas diferentes. Isso é comprovado na próxima linha quando você pode alterar o nome de uma das estruturas e a outra permanece inalterada.
Alex Wayne

Só perdi a tarefa. Está claro, obrigado. Talvez ele fora muito quente :-)
Julian Król

60

Tanto a classe quanto a estrutura podem fazer:

  • Definir propriedades para armazenar valores
  • Definir métodos para fornecer funcionalidade
  • Seja estendido
  • Conformidade com protocolos
  • Definir intialisadores
  • Definir Subscritos para fornecer acesso às suas variáveis

Somente a classe pode fazer:

  • Herança
  • Tipo de fundição
  • Definir desinicializadores
  • Permitir a contagem de referências para várias referências.

32

structsão tipos de valor. Isso significa que, se você copiar a instância da estrutura para outra variável, ela será copiada para a variável.

Exemplo para o 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

Classes são tipos de referência. Isso significa que, se você atribuir uma instância da classe a uma variável, ela conterá apenas a referência à instância e não a cópia .


5
+1 para "Se você atribuir uma instância da classe a outra variável, ela conterá apenas a referência da instância que não será copiada".
Saif

8

As respostas acima estão corretas. Espero que minha resposta ajude alguém que não entende as respostas acima.

Bem no Swift Existem dois tipos de objetos

  1. Struct
  2. Classe

A principal diferença entre eles é

  • Struct é o tipo de valor
  • Classe é tipo de referência

Por exemplo, aqui código para entender bem.

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

Essa foi a principal diferença, mas também temos sub diferenças.

Classe

  1. É necessário declarar inicializador (construtor)
  2. Possui desinicializadores
  3. Pode herdar de outras classes

Struct

  1. Possui inicializador gratuito para você, você não precisa declarar inicializador, se o inicializador gratuito for substituído pelo inicializador declarado
  2. Não tem desinicializador
  3. Não é possível herdar de outra estrutura

7

Essa pergunta parece estar duplicada, mas, independentemente disso, o seguinte responderia à maioria dos casos de uso:

  1. Uma das diferenças mais importantes entre estruturas e classes é que as estruturas são tipos de valor e sempre são copiadas quando transmitidas em seu código, e as classes são do tipo referência e são transmitidas por referência.

  2. Além disso, as classes possuem herança, o que permite que uma classe herde as características de outra.

  3. As propriedades de estrutura são armazenadas nas instâncias de pilha e classe, portanto, às vezes a pilha é drasticamente mais rápida que uma classe.

  4. O Struct obtém um inicializador padrão automaticamente, enquanto que na classe precisamos inicializar.

  5. Struct é thread thread safe ou singleton a qualquer momento.

E também, para resumir a diferença entre estruturas e classes, é necessário entender a diferença entre os tipos de valor e referência.

  1. Quando você faz uma cópia de um tipo de valor, ele copia todos os dados da coisa que você está copiando para a nova variável. São duas coisas separadas e a mudança de uma não afeta a outra.
  2. Quando você faz uma cópia de um tipo de referência, a nova variável se refere ao mesmo local da memória que está sendo copiado. Isso significa que mudar um mudará o outro, pois ambos se referem ao mesmo local de memória. O código de exemplo abaixo pode ser tomado como referência.

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

Resultado:

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

Oi Dilip, Você pode dar um exemplo para "Struct is thread safe ou singleton a qualquer momento". Desde já, obrigado.
Narasimha Nallamsetty

3

Se você olhar mais longe no manual da apple, verá esta seção: “Estruturas e enumerações são tipos de valor”

Nesta seção, você verá o seguinte:

“Deixe hd = Resolução (largura: 1920, altura: 1080) var cinema = hd Este exemplo declara uma constante chamada hd e a define como Resolução instância inicializada com a largura e a altura do vídeo em Full HD (largura de 1920 pixels por 1080 pixels de altura).

Em seguida, ele declara uma variável chamada cinema e a define como o valor atual de hd. Como Resolução é uma estrutura, é feita uma cópia da instância existente e essa nova cópia é atribuída ao cinema. Embora o hd e o cinema tenham agora a mesma largura e altura, são dois casos completamente diferentes nos bastidores.

Em seguida, a propriedade width do cinema é alterada para ser a largura do padrão 2K um pouco mais amplo usado para projeção de cinema digital (2048 pixels de largura e 1080 pixels de altura):

Cinema. Width = 2048 A verificação da propriedade width do cinema mostra que ele realmente mudou para 2048:

Println ("cinema é agora (cinema. Largura) pixels de largura") // imprime "cinema agora é 2048 pixels de largura No entanto, a propriedade width da instância hd original ainda possui a antiga valor de 1920:

println ("o HD ainda está (largura do HD) pixels de largura") // imprime "o HD ainda tem a largura de 1920 pixels"

Quando o cinema recebeu o valor atual de hd, os valores armazenados em hd foram copiados para a nova instância de cinema. O resultado final são duas instâncias completamente separadas, que contêm os mesmos valores numéricos. Por serem instâncias separadas, definir a largura do cinema para 2048 não afeta a largura armazenada no hd. ”

Trecho de: Apple Inc. “A linguagem de programação Swift”. iBooks. https://itun.es/us/jEUH0.l

Essa é a maior diferença entre estruturas e classes. As estruturas são copiadas e as classes são referenciadas.


1

Geralmente (na maioria das linguagens de programação), os objetos são blocos de dados armazenados na pilha e, em seguida, uma referência (normalmente um ponteiro) a esses blocos contém um name está sendo usado para acessar esses blocos de dados. Esse mecanismo permite o compartilhamento de objetos na pilha, copiando o valor de suas referências (ponteiros). Esse não é o caso de tipos de dados básicos, como Inteiros, e isso ocorre porque a memória necessária para criar uma referência é quase a mesma que o objeto (nesse caso, valor inteiro). Assim, eles serão passados ​​como valores e não como referência no caso de objetos grandes.

Swift usa struct para melhorar o desempenho, mesmo com objetos String e Array.

Uma leitura muito boa aqui


1

Para entender a diferença entre estruturas e classes, precisamos conhecer a principal diferença entre os tipos de valor e referência. Estruturas são tipos de valor e isso significa que todas as alterações nelas apenas modificarão esse valor, Classes são tipos de referência e todas as alterações em um tipo de referência modificarão o valor alocado naquele local de memória ou referência. Por exemplo:

Vamos começar com uma classe, essa classe está em conformidade com o Equatable apenas para poder comparar instâncias, criamos uma instância chamada pointClassInstanceAe outra chamamos a pointClassInstanceBclasse A à classe B, agora a asserção diz que são iguais ...

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, o que aconteceu aqui, por que, se apenas mudássemos o valor x de pointsClassInstanceB, ele também alteraria o valor x de pointClassInstanceA? bem, isso mostra como os tipos de referência funcionam, quando atribuímos a instância A como um valor da instância B e, em seguida, modificamos X de um deles, ele altera os dois Xs porque eles compartilham a mesma referência e o que mudou foi o valor dessa referência.

Vamos fazer o mesmo, mas com uma estrutura

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

Temos basicamente a mesma estrutura da nossa classe, mas agora você pode ver que, quando você imprime o valor x de pointStructInstanceA, neste caso, isso não mudou, e isso ocorre porque os tipos de valor funcionam de maneira diferente e todas as alterações em uma de suas instâncias serão " independente "e não afetará o outro.

Swift sugere usar mais tipos de valor e você pode dizer que suas bibliotecas são baseadas em estruturas para evitar os problemas que os tipos de referência trazem, como modificar acidentalmente um valor etc. Estruturas são o caminho a seguir no Swift. Espero que ajude.


1

Aqui está um exemplo que mostra a diferença entre struct e classe com precisão.

captura de tela do código escrito no playground
captura de tela do código escrito no playground

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 é um tipo cujo valor é copiado quando é atribuído a uma variável ou constante ou quando é passado para uma função

Reference types não são copiados quando atribuídos a uma variável ou constante ou quando são passados ​​para uma função

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

  • Quando você atribui ou passa value type uma nova cópia dos dados, é criada. Na verdade, o mecanismo copy on write- COWé usado com algumas otimizações, por exemplo, a cópia é criada quando o objeto é modificado
  • Quando você modifica uma instância, ela tem apenas efeito local .
  • A pilha de memória é usada.

Tipo de referência :
Class,Function

  • Quando você atribui ou passa reference typeuma nova referência à instância original, é criada (o endereço da instância é copiado).
  • Quando você modifica uma instância, ela tem um efeito global porque a instância é compartilhada e acessível por qualquer referência que aponte nela.
  • A memória da pilha é usada.

insira a descrição da imagem aqui

Value typeé recomendável usar por padrão . A maior vantagem Value typeé que geralmente eles sãothread safe

Reference type Prós:

  • eles podem ser herdados,
  • deinit() pode ser usado,
  • compare instâncias por referência ===,
  • Objective-Cinteroperabilidade porque Value Typefoi introduzida no Swift.

[Mais sobre mutabilidade]
Escolhendo entre
tipos de estruturas e classes
Classes e estruturas


0

Já há muito escrito sobre isso, eu gostaria de adicionar uma analogia lá. Espero que você nunca tenha dúvidas em mente depois disso: Conclusão: as classes são passadas por referência, enquanto as estruturas são passadas por valor.

Suponha que você esteja compartilhando uma folha de documentos do Google com seu amigo. Agora, se ele mudar alguma coisa, você também verá que as alterações no seu documento do Google significam que sua cópia também é afetada. Isso é basicamente " passado por referência ".

Mas suponha que, se você tiver um arquivo .XLS salvo em sua máquina. Você fornece esse arquivo para seu amigo. Agora, se ele estiver fazendo alguma alteração nesse arquivo, seu arquivo não será bagunçado / afetado porque você tem sua própria cópia. Isso é basicamente " passado por valor ". Você já tem vários programas simples para verificar essa analogia em playgrounds rápidos.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.