Estruturas e classes são os blocos de construção de construções flexíveis, ajudando os desenvolvedores a decidir como armazenar dados e o comportamento do modelo em seus programas. As classes no Swift costumam ser vistas como um projeto para a criação de objetos.

Com a capacidade de armazenar valores definindo propriedades e adicionando funcionalidade por meio da criação de métodos, os recursos compartilhados de classes e estruturas podem ser usados ​​alternadamente no Swift. No entanto, ambos têm diferenças e exclusividade, trazendo flexibilidade aos desenvolvedores para usá-los onde acharem melhor.

Revisaremos as semelhanças e diferenças entre classes e estruturas, bem como revisaremos como funcionam dentro do código.

Visão geral das semelhanças e diferenças de classes e estruturas do Swift

As semelhanças entre classes e estruturas em Swift oferecem intercambialidade e flexibilidade. Por exemplo, conforme mencionado anteriormente, ambas as classes e estruturas podem definir propriedades para armazenar valores, fornecendo diferentes opções para armazenar dados e modelar o comportamento no código.

Outras semelhanças incluem:

  • Inicializadores que configuram valores de estado inicial usando a palavra-chave init ()
  • A capacidade de definir subscritos , fornecendo acesso rápido ao valor, coleção ou lista
  • A capacidade de estender uma classe ou estrutura usando a extensão palavra-chave
  • Conformidade do protocolo

As classes, no entanto, têm recursos adicionais que as diferenciam dos structs. As classes podem herdar todas as propriedades, comportamentos e métodos de outra classe, bem como adicionar recursos extras ao que é herdado

A outra diferença é a conversão de tipo, que permite aos desenvolvedores verificar e interpretar um tipo de instância de classe em tempo de execução.

Semelhanças de sintaxe de classe e estrutura em Swift

A sintaxe para definir classes e estruturas em Swift também são semelhantes. Para definir uma classe ou estrutura em Swift, use a palavra-chave classe ou estrutura seguida do nome da classe ou estrutura com chaves.

Como observação, certifique-se de que os nomes das classes e estruturas em Swift sigam a convenção de nomenclatura PascalCase.

Em nosso exemplo, vamos criar uma classe e uma estrutura com o nome Usuário :

 class User { ...
}
 struct User {
...
}

Agora podemos adicionar definições de classes e estruturas ao nosso código.

Definição de classe

Quando criamos nossa classe e adicionamos definições de classe, podemos fornecer valores padrão, tornar as definições opcionais ou criar nosso próprio inicializador.

Em Swift, toda classe deve ter um inicializador. Se uma classe possui subclasses, o inicializador garante ao compilador que as subclasses herdarão ou implementarão o mesmo inicializador. Isso nos permite definir definições de classe.

Por exemplo, podemos criar um inicializador personalizado no código a seguir, definindo firstName como String para inicializar e atribuir firstName alguns valores:

 class User { var firstName: String var lastName: String var gender: String init (firstName: String, lastName: String, gender: String) { self.firstName=firstName self.lastName=lastName self.gender=gênero }
}

Observe que em self.firstName=firstName , self.firstName se refere ao firstName que definimos em nosso var firstName: Classe String . self refere-se à instância atual de User .

Quando as propriedades da classe User têm valores padrão, a classe User implementa automaticamente um inicializador padrão, criando uma nova instância com suas propriedades definidas para seus valores padrão.

Para uma definição de classe com valores padrão, podemos adicionar o seguinte:

 class User { var firstName="Ejiro" var lastName="Asiuwhu" var gênero="masculino"
}

Se não tivermos certeza se queremos uma variável para conter um valor ou atribuir um valor mais tarde, podemos tornar a variável opcional. Para uma definição de classe com valores opcionais, podemos adicionar o seguinte:

 classe NewUser { var firstName: String? var lastName: String? var age: Int?
}

Definição de estrutura

Só existe uma maneira de definir uma estrutura em Swift:

 struct User { var firstName="Ejiro" var lastName="Asiuwhu" var gênero="masculino"
}

Criando instâncias de classe Swift

Instâncias de classe em Swift são conhecidas como objetos. Para usar a classe User que criamos anteriormente, devemos criar uma instância:

 class User {
//definição de classe var firstName: String var lastName: String var gender: String var age: Int //criando nosso initilizer init (firstName: String, lastName: String, gender: String, age: Int) { self.firstName=firstName self.lastName=lastName self.gender=gênero self.age=age }
} //criando uma instância de classe
let person: User=User (firstName:"Ejiro", lastName:"Asiuwhu", gênero:"masculino", idade: 45)

É importante notar que as instâncias da classe Swift são objetos mutáveis, enquanto as instâncias de struct são valores imutáveis. Como as classes são um tipo de referência, todas as alterações feitas em uma variável atribuída a uma instância de classe afetam a classe original, tornando-a mutável.

Por outro lado, como as estruturas são um tipo de valor, quaisquer alterações feitas em uma variável atribuída a uma instância de estrutura afetam a estrutura original, tornando seu valor imutável.

Acessando propriedades de instâncias de classe

Quando precisamos acessar os dados de uma classe, podemos usar a notação de ponto. Por exemplo, para acessar a propriedade age de nossa classe User que criamos em nosso exemplo anterior, podemos adicionar o seguinte:

//criando uma instância de classe
let person: User=User (firstName:"Ejiro", lastName:"Asiuwhu", gênero:"male", age: 45)
person.age//saída esperada: 45

Além de acessar dados, também podemos usar a sintaxe de notação de ponto para definir valores para propriedades variáveis, o que nos permite adicionar dados adicionais:

//criando uma instância de classe
let person: User=User (firstName:"Ejiro", lastName:"Asiuwhu", gênero:"male", age: 45)
person.age=78//saída esperada: 78

Criação de métodos Swift em classes e estruturas

Ambas as classes e estruturas do Swift podem definir métodos para fornecer funcionalidade. Usando a palavra-chave func para criar um método em nossa classe User , podemos adicionar getDetails () para acessar informações como firstName , lastName , age e gender :

 class User {
//definição de classe var firstName: String var lastName: String var gender: String var age: Int
//criando nosso initilizer init (firstName: String, lastName: String, gender: String, age: Int) { self.firstName=firstName self.lastName=lastName self.gender=gênero self.age=age } //métodos em classes Swift
func getDetails () { print ("\ (firstName) \ (lastName) tem \ (idade) anos \ (gênero)") }
//criando uma instância de classe
let person: User=User (firstName:"Ejiro", lastName:"Asiuwhu", gênero:"masculino", idade: 45) //tema
person.getDetails ()//saída esperada: Ejiro Asiuwhu é um homem de 45 anos

Observe como o método getDetails () recém-criado agora está disponível em nossa instância de classe. Podemos acessar o método usando a notação de ponto na instância let person: User=User , seguida por parênteses que chamam func .

Da mesma forma, também podemos definir métodos em estruturas com notação de ponto para fornecer funcionalidade:

 struct User { var firstName: String var lastName: String var gender: String var age: Int func getDetails () { print ("\ (firstName) \ (lastName) tem \ (idade) anos \ (gênero)") }
}
let person: User=User (firstName:"Ejiro", lastName:"Asiuwhu", gênero:"masculino", idade: 45)
person.getDetails ()//saída esperada: Ejiro Asiuwhu é um homem de 45 anos

Diferenças de classe Swift

Herança de classe

A herança é um recurso fundamental nas classes que os diferencia dos structs. Compreender como funciona a herança é importante ao decidir se deve usar uma classe ou estrutura ao escrever Swift.

A subclasse nos permite herdar de uma classe para outra, o que significa que uma classe (designada como subclasse) acessa todos os dados, como propriedades e métodos, de outra classe (designada como superclasse) .

Para começar a criar uma subclasse, devemos definir nossa superclasse e, em seguida, basear uma nova subclasse na superclasse existente.

A criação de subclasses também não nos limita, porque podemos adicionar mais funcionalidades e propriedades à nossa subclasse, independentemente do que herdamos.

Para entender como a herança funciona nas classes Swift, vamos reutilizar nossa classe User como uma superclasse e criar uma subclasse chamada Admin para herdar o User propriedades:

 class User {
//definição de classe var firstName: String var lastName: String var gender: String var age: Int
//criando nosso initilizer init (firstName: String, lastName: String, gender: String, age: Int) { self.firstName=firstName self.lastName=lastName self.gender=gênero self.age=age }
}
class Admin: User { var autorizar: Bool?
}
var admin=Admin (primeiroNome:"Ejiro", sobrenome:"Asiuwhu", gênero:"masculino", idade: 45)
admin.authorize=true; imprimir (admin.authorize)//resultado esperado: verdadeiro

Observe como refinamos a subclasse Admin adicionando mais propriedades além da herdada da superclasse User .

Valores e referências

Um recurso fundamental que diferencia structs e classes é que structs são tipos de valor e classes são tipos de referência.

Ao criar uma estrutura e atribuí-la a uma variável, o valor é copiado porque é um tipo de valor. Ao definir os valores da estrutura point2 como o valor da estrutura point1 , estamos criando uma cópia separada de cada variável.

Portanto, quando os valores de ponto1 são alterados, isso não afeta os valores de ponto2 :

 struct Coordinates { var lat: Double var lng: Double
} var point1: Coordenadas=Coordenadas (lat: 5.519, lng: 5.7599)
//aqui, estamos definindo os valores de ponto2 para ser o valor de ponto1
var ponto2: Coordenadas=ponto1 ponto2.lat=6,45
point2.lng=8,211 imprimir (ponto2)//saída esperada: Coordenadas (lat: 6,45, lng: 8,211)
imprimir (ponto1)//saída esperada: Coordenadas (lat: 5.519, lng: 5.7599)

Mas quando as classes são atribuídas a uma variável, ela faz referência à instância existente em vez de copiá-la:

 class User { var firstName: String var lastName: String var gender: String var age: Int init (firstName: String, lastName: String, gender: String, age: Int) { self.firstName=firstName self.lastName=lastName self.gender=gênero self.age=age }
} var user1: User=User (firstName:"Ejiro", lastName:"Asiuwhu", gênero:"male", age: 29)
//user2 agora possui o mesmo valor que user1
var user2: User=user1 user1.age=30 imprimir (user1.age)//saída esperada: 30
imprimir (user2.age)//saída esperada: 30

Observe a diferença entre os tipos de valor e de referência aqui: quando um valor muda em um tipo de referência, todas as variáveis ​​referenciadas também mudam.

Como vemos em nossa classe acima, user1.age e user2.age agora têm o mesmo valor. Isso ocorre porque user1 não é apenas uma cópia de user2 , mas sim user1 é user2 .

Quando armazenamos uma classe, armazenamos seu valor na memória e uma variável que aponta para uma classe contém apenas uma referência à classe.

Quando adicionamos var user2: User=user1 para nossa classe, estamos dizendo a user2 para fazer referência a user1 , colocando todos os dados em ambas as variáveis ​​em sincronia. Se mudarmos um deles, o outro muda.

Quando usar classes vs. estruturas em Swift

A documentação oficial da apple recomenda amplamente que os usuários usem structs por padrão. Isso ocorre principalmente porque os structs são muito mais seguros e livres de bugs, especialmente em um ambiente multithread. Structs também são preferíveis se forem relativamente pequenos e copiáveis, porque copiar structs é mais seguro do que ter várias referências para a mesma instância.

Ao escolher entre structs e classes, é importante lembrar as principais diferenças:

  • Classes são tipos de referência e structs são tipos de valor
  • Se a herança de classe não for necessária, as estruturas são mais rápidas e mais eficientes em termos de memória
  • Use estruturas para cópias exclusivas de um objeto com estados independentes
  • Use structs ao trabalhar com alguns valores de dados relativamente simples
  • Use classes para acessar o tempo de execução Objective-C
  • Use classes para controlar a identidade de um objeto
  • Use structs quando não houver necessidade de controlar a identidade de um objeto

Classes e estruturas fornecem flexibilidade ao trabalhar em Swift. Embora sejam geralmente intercambiáveis, seus recursos ligeiramente diferentes fornecem aos desenvolvedores as opções de que precisam.

Sinta-se à vontade para deixar um comentário e me dizer o que você achou deste artigo. Você também pode me encontrar no Twitter e no GitHub . Obrigado por ler!

A postagem Introdução às classes e estruturas em Swift apareceu primeiro no LogRocket Blog .