Entre para a LISTA VIP da Black Friday

00

DIAS

00

HORAS

00

MIN

00

SEG

Clique para saber mais
Alura > Cursos de Mobile > Cursos de iOS > Conteúdos de iOS > Primeiras aulas do curso Swift: entendendo e praticando orientação a objetos

Swift: entendendo e praticando orientação a objetos

Structures e Classes - Apresentação

Olá! Sou a Giovanna Moeller e sou instrutora aqui na Alura.

Autodescrição: sou uma mulher branca de cabelos loiros e estou vestindo uma blusa azul com estampa branca. Estou à frente de uma parede com fundo degradê das cores azul para rosa.

Quero te dar boas-vindas ao curso de Swift: orientação a objetos. Durante esse curso continuaremos nossos estudos na linguagem Swift, a linguagem que usamos para desenvolver aplicativos iOS.

Em cada uma das aulas será introduzido um novo conceito sobre a linguagem e ao final de cada aula será proposto um desafio. É extremamente importante que você faça os desafios para fixar melhor os seus conhecimentos.

Neste curso aprenderemos sobre:

E também veremos sobre outros tipos de dados que são extremamente importantes na linguagem Swift:

Pré-requisitos

Para fazer este curso você precisa ter familiaridade com a linguagem Swift. Por isso é importante que você tenha feito o curso Swift: entendendo a linguagem.

E aí, bora iniciar o curso? Te espero na primeira aula!

Structures e Classes - Structs

Durante esse curso, vamos desenvolver uma espécie de projeto que sirva como código inicial para nossa aplicação.

Imagine que estamos fazendo o esboço de um aplicativo que representa um banco e precisamos de uma estrutura para simular uma conta-corrente.

Em uma conta-corrente podemos ter uma variável que represente o saldo, por exemplo. Também podemos ter métodos ou funções como Sacar, que vai tirar um valor desse saldo, e Depositar, que vai inserir um valor nesse Saldo.

Mas como podemos trazer esse exemplo para programação na linguagem Swift? Que tipo de dados podemos usar para criar nossas próprias variáveis, métodos e funções dentro desse tipo de dado?

Podemos criar um tipo de dados customizado que sirva como um molde para conta-corrente.

Se você já vem de alguma outra linguagem de programação, provavelmente já ouviu falar sobre Classes, é exatamente com isso que vamos trabalhar.

No Swift, além de classes também temos as Structs. Vamos iniciar nossos estudos pelas Structs, que são bem parecidas com as classes.

Structs

Como podemos definir uma struct e começar a utilizá-la?

Já estou com meu arquivo MyPlayground aberto. Precisamos começar a escrever o código definindo uma struct pela palavra-chave struct, seguida do nome dela que será ContaCorrente. É uma boa prática, ao criar um novo tipo de dado, que a primeira letra seja maiúscula. Em seguida vamos abrir e fechar chaves, porque todo o código relacionado a essa struct estará dentro das chaves.

struct ContaCorrente {

}

Começaremos criando a variável saldo e vamos atribuir a ela o valor 0.0, significando que é um tipo double, que é um número decimal.

struct ContaCorrente {
    var saldo = 0.0

}

Quando falamos de variáveis no contexto de structs e classes, nós as referenciamos como atributos.

Agora, vamos criar métodos. Métodos são funções. Quando falamos sobre structs e classes, e falamos sobre funções, na verdade, estamos falando sobre métodos. Assim como variáveis são chamadas de atributos.

Na linha 4, criaremos uma função chamada sacar() que vai receber valor do tipo double.

struct ContaCorrente {
    var saldo = 0.0

    func sacar(_ valor: Double){

    }
}

Dentro dessa função vamos tirar do saldo, então saldo sinal de menos e igual a valor: saldo -= valor.

struct ContaCorrente {
    var saldo = 0.0

    func sacar(_ valor: Double){
        saldo -= valor
     }
}

Você deve ter percebido que a linha saldo -= valor provocou um erro na nossa IDE, isso acontece porque quando utilizamos structs não podemos alterar um atributo da nossa struct dentro de uma função. Nesta linha estamos modificando o atributo saldo. Isso não é possível originalmente.

Mas podemos escrever a palavra-chave mutating antes de func sacar. Isso significa que essa função é do tipo mutating, ou seja, com ela indicamos que podemos alterar um atributo dessa struct dentro de um método.

Note que agora o código executou sem problemas. Em seguida vamos criar outro método, o depositar(), que vai receber valor double. Ele receberá saldo mais igual valor, saldo += valor.

struct ContaCorrente {
    var saldo = 0.0

    mutating func sacar(_ valor: Double){
        saldo -= valor
        }

        mutating func depositar(_ valor: Double){
        saldo += valor

        }

}

Se executarmos esse código, nada vai acontecer. Porque a struct funciona como um molde, estamos apenas representando os dados.

Agora precisamos, de fato, instanciar essa struct, criar objetos.

Na linha 13, vamos criar uma variável contaCorrenteGiovanna e vamos atribuir essa variável a uma instância de ContaCorrente:

var contaCorrenteGiovanna = ContaCorrente()

Agora, podemos acessar atributos e métodos da struct ContaCorrente. Se exibirmos no console contaCorrenteGiovanna.saldo, o console vai exibir que o saldo é de 0.0.

var contaCorrenteGiovanna = ContaCorrente()
print(contaCorrenteGiovanna.saldo)

0.0

Agora vamos utilizar o método depositar() colocaremos 1500 reais e vamos exibir o saldo novamente no console.

struct ContaCorrente {
var saldo = 0.0

mutating func sacar(_ valor: Double) {
saldo -= valor
}
mutating func depositar(_ valor: Double) {
saldo += valor
  }
}

var contaCorrenteGiovanna = ContaCorrente()
print(contaCorrenteGiovanna.saldo)
contaCorrenteGiovanna.depositar(1500)
print(contaCorrenteGiovanna.saldo)

0.0

1500.0

Agora o console retornou um saldo de 1500.

Claro que podemos explorar esses métodos de uma forma um pouco melhor. Por exemplo, não podemos depositar um valor negativo. Poderíamos criar uma condicional para não permitir esse tipo de ação.

Já instanciamos um objeto e podemos instanciar diversos outros.

Vamos criar uma nova variável chamada contaCorrenteCaio e instanciar a struct ContaCorrente novamente. Agora vamos depositar na conta do Caio o valor de 200 reais. E exibiremos o saldo da contaCorrenteCaio no console.

struct ContaCorrente {
var saldo = 0.0

mutating func sacar(_ valor: Double) {
saldo -= valor
}
mutating func depositar(_ valor: Double) {
saldo += valor
  }
}

var contaCorrenteGiovanna = ContaCorrente()
print(contaCorrenteGiovanna.saldo)
contaCorrenteGiovanna.depositar(1500)
print(contaCorrenteGiovanna.saldo)

var contaCorrenteCaio = ContaCorrente()
contaCorrenteCaio.depositar(200)
print(contaCorrenteCaio.saldo)

0.0

1500.0

200.0

Agora, vamos sacar um valor da conta do Caio. Abaixo da linha contaCorrenteCaio.depositar(200) vamos inserir o método sacar() para sacar 100 reais: contaCorrenteCaio.sacar(100).

var contaCorrenteCaio = ContaCorrente()
contaCorrenteCaio.depositar(200)
contaCorrenteCaio.sacar(100)
print(contaCorrenteCaio.saldo)

Ao executar o código teremos:

0.0

1500.0

100.0

O saldo da contaCorrenteCaio agora é de 100.

Podemos perceber que na struct temos um atributo que já está inicializado, porque quando criamos uma conta-corrente o nosso saldo começa vazio. Podemos ter um atributo que seja customizado para cada instância dessa struct.

Por exemplo, podemos criar uma variável nome. Não vou inicializá-la, por isso precisamos declarar explicitamente o tipo desse atributo var nome: string.

struct ContaCorrente {
var saldo = 0.0
var nome: String
mutating func sacar(_ valor: Double) {
saldo -= valor
}
mutating func depositar(_ valor: Double) {
saldo += valor
  }
}

Agora, na linha devar contaCorrenteGiovanna = ContaCorrente() e na linha de var contaCorrenteCaio = ContaCorrente() a IDE está indicando um erro "Missing argument for parameter'nome' in call", ou seja, informando que não passamos nenhum argumento relacionado a nome.

A indicação é que devemos colocar algo seguindo o modelo nome: String. Então na contaCorrenteGiovanna colocaremos nome: "Giovanna" e na contaCorrenteCaio colocaremos nome: "Caio".

var contaCorrenteGiovanna = ContaCorrente(nome: "Giovanna")
print(contaCorrenteGiovanna.saldo)
contaCorrenteGiovanna.depositar(1500)
print(contaCorrenteGiovanna.saldo)

var contaCorrenteCaio = ContaCorrente(nome: "Caio")
contaCorrenteCaio.depositar(200)
contaCorrenteCaio.sacar(100)
print(contaCorrenteCaio.saldo)

Com isso, estamos passando valores customizados. Porque realmente o nome é diferente para cada instância, cada pessoa tem sua própria conta-corrente. Por isso passamos parâmetros customizados.

Recapitulando, as structs são um tipo de dado complexo e você pode definir suas próprias structs, com seus próprios atributos e métodos.

No próximo vídeo, aprenderemos sobre classes. Te espero lá!

Structures e Classes - Classes

Agora que você já aprendeu sobre structs, está na hora de aprender sobre classes. São bem parecidos, mas em breve vou explicar a diferença entre os dois e quando utilizar cada um deles.

Vamos continuar no código do vídeo anterior. Faremos algumas modificações nele.

Primeiro, precisamos mudar de struct para classe. Na linha 1, substituiremos struct por class.

class ContaCorrente {
    var saldo = 0.0
    var nome: String

//código omitido

Se executarmos, vários erros serão apontados pela IDE, vamos passar em cada um deles e corrrigi-los.

O primeiro erro que quero pontuar é o erro da linha 5, mutating func sacar(_ valor: Double), ele indica que a palavra "mutating" não é válida em instâncias de classes.

'mutating' is not valid on instance methods in classes

Remove 'mutating'

Isso significa que não precisamos utilizar a palavra-chave mutating para alterar atributos de uma classe. Então vamos simplesmente apagar a palavra "mutating" da linha 5 e da linha 9.

Outro erro que está sendo indicado é na linha 1. Está indicando que a classe ContaCorrente não possui nenhum inicializador.

Class 'ContaCorrente' has no initializers

O que isso significa? O nosso atributo nome não é inicializado, simplesmente declaramos como uma string e passamos como parâmetro ao instanciar uma struct.

No caso das classes, precisamos utilizar o que chamamos de "Construtor", que é o método que vai inicializar essas variáveis. Então, na linha 13, abaixo da função depositar()vamos inserir o init():

init() {

}

Dentro desse init() precisamos inicializar todos os atributos da nossa classe. Então, no início no código, podemos apagar o 0.0 e escrever "Double", vamos definir explicitamente o tipo desse atributo.

class ContaCorrente {
    var saldo = Double
    var nome: String

//código omitido

Agora, no init() vamos escrever saldo igual a 0.0, para inicializar esse atributo saldo.

init() {
        saldo = 0.0
}

Além disso, precisamos inicializar também o atributo nome. Mas o atributo nome, como ele muda de instância para instância, precisamos passar como um parâmetro. Dentro do parênteses do init() vamos escrever nome: String.

init(nome: String) {
        saldo = 0.0
}

Agora precisamos que o atributo nome de dentro da classe seja igual ao parâmetro que estamos passando para o construtor. Mas se fizermos nome = nome não vai fazer muito sentido. Então, para referenciarmos o nome como um atributo da classe precisamos escrever self antes. Vamos escrever self.nome = nome.

    init(nome: String) {
        saldo = 0.0
        self.nome = nome
    }

O que isso significa? Significa que o atributo nome da classe ContaCorrente está sendo igualado a o que estamos recebendo como parâmetro nesse construtor.

Se executarmos o código agora, nenhum erro será apontado.

class ContaCorrente {
    var saldo: Double
    var nome: String

    func sacar(_ valor: Double) {
        saldo -= valor
    }

    func depositar(_ valor: Double) {
        saldo += valor
    }

    init(nome: String) {
        saldo = 0.0
        self.nome = nome
    }
}

var contaCorrenteGiovanna = ContaCorrente(nome: "Giovanna")
print(contaCorrenteGiovanna.saldo)
contaCorrenteGiovanna.depositar(1500)
print(contaCorrenteGiovanna.saldo)

var contaCorrenteCaio = ContaCorrente(nome: "Caio")
contaCorrenteCaio.depositar(200)
contaCorrenteCaio.sacar(100)
print(contaCorrenteCaio.saldo)

Tivemos o seguinte retorno no console:

0.0

1500.0

100.0

Já vimos duas diferenças entre structs e classes. As structs precisam da palavra-chave mutating para as funções que alteram um atributo da struct. Porém, as structs possuem um inicializador que funciona "por debaixo dos panos", não precisamos defini-lo. Mas isso não acontece com classes. Com classes é obrigatório definir o construtor quando não estamos inicializando todos os atributos no momento de execução do código.

Agora você tem sua primeira classe criada. A maneira de instância é a mesma que da struct, nem mudamos nada em relação às variáveis que criamos para instanciar uma classe. Tudo está funcionando como esperado.

Ao longo desta aula vamos explorar outras diferenças entre structs e classes. Te espero no próximo vídeo!

Sobre o curso Swift: entendendo e praticando orientação a objetos

O curso Swift: entendendo e praticando orientação a objetos possui 111 minutos de vídeos, em um total de 39 atividades. Gostou? Conheça nossos outros cursos de iOS em Mobile, ou leia nossos artigos de Mobile.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda iOS acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas