Alura > Cursos de Mobile > Cursos de Flutter > Conteúdos de Flutter > Primeiras aulas do curso Dart: trabalhando com orientação a objetos

Dart: trabalhando com orientação a objetos

Criando uma conta - Apresentação

Olá, meu nome é Matheus Marcus e sou instrutor aqui na Alura.

Audiodescrição: Matheus se declara uma pessoa branca, de cabelos lisos castanho-escuro. Está vestindo uma camiseta preta e usando um brinco de argola preta pequeno na orelha esquerda. À sua fente está um microfone preto em um suporte. Atrás dele tem uma parede lisa iluminada por uma luz led roxa.

Acompanharei você durante esse curso chamada "Dart: trabalhando com orientação a objetos".

O que aprenderemos

Dart é uma linguagem voltada à orientação a objetos. O que significa? E quais são os problemas que ela resolve?

Neste curso, descobriremos exatamente isso. Aprenderemos, na prática, como podemos aplicá-la para resolver problemas que encontramos comumente no mundo da programação.

O projeto

Desenvolveremos o projeto do Anybank, um banco que está passando por um processo de atualização do seu sistema. Nossa tarefa será transformar tudo o que já existia em Dart.

Então, criaremos um sistema funcional, onde teremos:

Ao final, teremos um banco funcionando no terminal: imprimindo saldo e realizando transferências. Tudo conforme as informações relacionadas entre si.

Visualizando o funcionamento

Abri o terminal do VS Code para mostrar um pouco desse programa.

Rodando o comando dart run, recebi um extrato impresso na tela com todas as transferências e transações que implementaremos no projeto. Temos o saldo de:

Os valores aparecem atualizados depois de cada uma das transferências e transações que realizamos com cada conta.

Pré-requisitos

Para acompanhar esse curso, é muito importante que você já tenha conhecimentos prévios de lógica de programação e os conhecimentos básicos da linguagem Dart.

Gostou? Tem interesse?

Vejo você no próximo vídeo então.

Criando uma conta - Criando a primeira classe com Dart

Estamos trabalhando em uma atualização para o banco da Anybank, onde transcreveremos tudo o que já existia naquele banco para o Dart agora. Nossa primeira tarefa será criar uma conta que guardará uma informação de titular e um saldo.

Criando uma conta

Vamos para a IDE, onde explicarei melhor o que faremos.

Começaremos salvando a conta do Matheus, o titular dessa conta. De alguma forma, precisamos vinculá-lo a um saldo, por exemplo, R$ 1.000 (mil reais).

Arquivo anybank.dart

void main() {
    Matheus - 1000
}

Podemos criar várias outas contas, por exemplo, a conta da Roberta, que terá o saldo de R$ 2.000 (dois mil reais).

void main() {
    Matheus - 1000
    Roberta - 2000
}

São essas duas informações que precisamos guardar: nome e saldo. Como fazer isso com o conhecimento que já temos?

Apagaremos o que escrevemos e criaremos listas, por ser uma forma que temos de guardar informações. Será uma lista do tipo string chamada contas. Nela contas, podemos começar a guardar "Matheus" e "Roberta".

Arquivo anybank.dart

void main() {
    List<String> contas = <String>["Matheus", "Roberta"];
}

Faremos outra lista, onde guardaremos os saldos. Ela será do tipo double e podemos chamá-la de saldos. Nela passaremos os 1000, do Matheus, e os 2000, da Roberta.

void main() {
    List<String> contas = <String>["Matheus", "Roberta"];
    List<double> saldos = <double>[1000, 2000];
}

Relacionando valores das listas

Como saberemos que essas informações estão vinculadas uma à outra? Como sabemos que esses R$ 1.000 são do Matheus e não da Roberta? Se tivéssemos duas contas com R$ 1.000, como saberíamos exatamente que o primeiro R$ 1.000 é do Matheus e o segundo R$ 1.000 é da Roberta?

Podemos usar o argumento. Como listas têm posições que vão de 0 até "N", podemos definir a posição 0 da lista de contas como a do Matheus, assim como a posição 0 da lista de saldos também é do Matheus. Conseguimos vincular com a posição das duas listas.

Entretanto, o que aconteceria se, em algum momento, alterarmos a ordem dessa lista? Seja, por exemplo, removendo uma conta, ou por outro motivo, a ordem mudará. Assim fica difícil relacionar.

Se pensarmos que titular e saldo são conjuntos de uma informação, podemos criar um conjunto que contém essas duas informações. Para isso, após o fechamento de chaves, pressionaremos "Enter" duas vezes e, abaixo da main(), criaremos um novo conjunto de informações chamado class (classe). Chamaremos essa classe de ContaMatheus e, para delimitar essa classe, usamos as chaves ({}), assim como delimitamos as funções, como a main().

void main() {
    List<String> contas = <String>["Matheus", "Roberta"];
    List<double> saldos = <double>[1000, 2000];
}

class ContaMatheus {

}

Agora, a ContaMatheus precisa de uma string, para o titular, e um double, para o saldo.

// código omitido

class ContaMatheus {
    String titular;
    double saldo;
}

Um detalhe: titular e saldo estão marcados como erro. Se passarmos o cursor por cima de titular, receberemos uma mensagem em inglês, da IDE, informando que "**titular precisa ser inicializado**". A mesma mensagem aparece para o saldo.

Precisamos inicializar essas variáveis para podermos realmente continuar as usando na ContaMatheus. Para isso, atribuiremos valor a essas variáveis, ou seja, Matheus e 1000.

// código omitido

class ContaMatheus {
    String titular = Matheus;
    double saldo = 1000;
}

Fizemos a nossa ContaMatheus, então o próximo passo seria fazer a ContaRoberta, seguindo os mesmos passos.

// código omitido

class ContaMatheus {
    String titular = Matheus;
    double saldo = 1000;
}

class ContaRoberta {
    String titular = Roberta;
    double saldo = 2000;
}

Salvamos nossas contas e não temos nenhum erro. Porém, temos uma classe para cada uma dessas contas.

Quantas contas será que tem no banco? Ter que criar uma classe nova para cada conta é trabalhoso, então talvez exista um jeito melhor de fazer isso. Um jeito no qual não precisamos repetir tantas vezes os códigos String titular e double saldo, simplesmente passamos as informações necessárias para gerar uma nova conta.

Criando contas a partir do modelo de classe

Realmente existe um jeito melhor de resolver esse problema, porque as classes em Dart são como moldes. A ideia é que realmente tenhamos esse conjunto de informações pré-definidas e, em algum momento, quando precisarmos preencher essa classe com informações, criamos uma classe nova sem precisar definir uma classe nova. Entenderemos um pouco melhor como isso funciona na prática.

Apagaremos a classe ContaRoberta, mantendo apenas a classe ContaMatheus. Entretanto, vamos alterá-la um pouco. Não queremos que esteja relacionada apenas ao Matheus, mas representando uma conta, que precisa do titular e do saldo. Para resolvermos isso, mudaremos o nome da classe apenas para Conta e apagaremos os valores que inicializamos antes.

// código omitido

class Conta {
    String titular;
    double saldo;
}

Com isso, voltamos ao mesmos erro de antes, porque ainda precisamos de uma forma de preencher esses dados, adicionando informações nessas variáveis. Para isso, precisamos pensar nas formas que conhecemos de atribuir valores a uma variável dentro do Dart.

Até o momento, conhecemos duas formas. A primeira é a atribuição de variáveis, como fizemos para colocar a lista de contas, a lista de saldos ou até mesmo colocar os valores dessas variáveis titular e saldo, como acabamos de fazer.

A outra forma é passando valores dentro de funções. Podemos criar uma função que receberá um valor e, em seguida, atribuímos os valores para os seus devidos lugares: titular e saldo. Entretanto, para classes, essa função é um pouco diferente.

Clicaremos no final de double saldo; e pressionaremos "Enter" duas vezes. Ainda dentro das chaves de Conta{}, criaremos uma função que tem o mesmo nome da classe, inclusive com o "C" maiúsculo.

// código omitido

class Conta {
    String titular;
    double saldo;
    
    Conta()
}

Nos parênteses, passamos os valores que ela precisa receber: titular e o saldo. Entretanto, precisamos referenciar o titular e o saldo desta conta.

Quando aprendemos sobre função, entendemos sobre escopo, ou seja, o espaço onde as variáveis tem acesso. Nesse caso, o escopo do nosso código é apenas a classe conta, e para referenciarmos alguma coisa dentro do próprio escopo, usamos a palavra-chave this. Então fica this.titular e this.saldo.

// código omitido

class Conta {
    String titular;
    double saldo;
    
    Conta(this.titular, this.saldo);
}

Entendendo a função

Essa é uma função um pouco diferente, porque precisamos passar o que tipo de valor que uma função retorna. Mesmo que ela não retorne nada, precisamos informar, através da palavra-chave void, como na função void main().

Porém, a função Conta() retorna uma conta, mas não podemos chamar o retorno de conta. Se pudéssemos, teríamos uma conta Conta(), ou uma conta novaFunção(). O caso da Conta() é o que chamamos de função construtora: uma função que serve para podermos construir essa classe.

Lembrete: A função construtora é uma função especial usada para contruir a classe, e não precisamos especificar o retorno dela.

E como criamos uma conta a partir da Conta()? Precisamos fazer a ContaMatheus e a ContaRoberta. Com o nosso molde criado, já temos uma forma de preenchê-lo com as informações, então podemos retornar à função main().

Usando a função construtora

Ao final da lista saldos, pressionaremos "Enter" duas vezes. Usaremos nossa função Conta() abaixo da definição das listas, dentro da função main().

Começaremos lembrando o tipo de retorno da função, que será uma própria conta. Portanto, criaremos uma variável do tipo Conta chamada contaMatheus, a qual atribuiremos a Conta().

Arquivo anybank.dart

void main() {
    List<String> contas = <String>["Matheus", "Roberta"];
    List<double> saldos = <double>[1000, 2000];
    
    Conta contaMatheus = Conta();
}

class Conta {
    String titular;
    double saldo;
    
    Conta(this.titular, this.saldo);
}

Fizemos uma chamada da Conta() como se fosse de uma função. É como se pedíssemos ao Dart "cria uma conta para mim, por favor?", e passamos as informações que essa conta precisa entre os parênteses. Primeiro o valor do titular, o "Matheus", e depois o valor do saldo, "1000".

void main() {
    List<String> contas = <String>["Matheus", "Roberta"];
    List<double> saldos = <double>[1000, 2000];
    
    Conta contaMatheus = Conta("Matheus", 1000);
}

//código omitido

Criamos a primeira conta, agora seguiremos os mesmo passos para criar a conta da Roberta:

void main() {
    List<String> contas = <String>["Matheus", "Roberta"];
    List<double> saldos = <double>[1000, 2000];
    
    Conta contaMatheus = Conta("Matheus", 1000);
    Conta contaRoberta = Conta("Roberta", 2000);
}

//código omitido

Conclusão

A nossa Conta serviu como um molde. Se quisermos criar diversas contas diferentes, podemos simplesmente chamar a nossa classe Conta e atribuir a função Conta() dentro dela, preenchendo as informações necessárias. Assim criamos uma variável do tipo Conta com todas aquelas informações.

Fizemos aquele conjunto e agora sabemos que uma contaMatheus ou uma contaRoberta terá tanto um valor de string titular quanto um valor de double saldo.

Criando uma conta - Criando objetos, acessando valores e guardando contas

Agora, com as classes, temos uma nova maneira de guardar as informações. Não precisamos mais das nossas listas para guardar contas e saldos separadamente.

Aprimorando o uso de listas

De volta ao nosso código, podemos apagar as listas conta e saldps, que criamos anteriormente.

void main() {
    Conta contaMatheus = Conta("Matheus", 1000);
    Conta contaMatheus = Conta("Roberta", 2000);
}

class Conta {
    String titular;
    double saldo;
    
    Conta(this.titular, this.saldo);
}

Agora podemos criar uma lista para guardar a contaRoberta e a contaMateus. Será uma lista do tipo <Conta>, que chamaremos de contas.

void main() {
    Conta contaMatheus = Conta("Matheus", 1000);
    Conta contaMatheus = Conta("Roberta", 2000);

    List<Conta> contas = <Conta>[contaMatheus, contaRoberta];
}

// código omitido

Acessando os resultados

Temos as nossas contas criadas e a nossa lista de contas, mas como acessamos as informações dessa conta? E, por exemplo, se fizemos transferências, como alteramos o valor do saldo? Precisaremos atribuir um novo valor à variável saldo.

Para poder acessar esses valores, podemos escrever o nome da nossa variável e adicionar um ponto (.) depois, por exemplo, contaMatheus.. Com esse . temos acesso às propriedades da classe. Então, ao final da lista contas, pressionaremos "Enter" duas vezes e escreveremos essa chamada.

void main() {
    Conta contaMatheus = Conta("Matheus", 1000);
    Conta contaRoberta = Conta("Roberta", 2000);

    List<Conta> contas = <Conta>[contaMatheus, contaRoberta];
    
    contaMatheus.
}

// código omitido

Com esse código, a própria IDE já nos recomenda o acesso às variáveis saldo e titular. Vamos escrever contaMateus.titular;. Assim temos a devolução de algo que não estamos vendo, então usaremos um print() em volta desse resultado, ou seja, print(contaMateus.titular);.

void main() {
    Conta contaMatheus = Conta("Matheus", 1000);
    Conta contaRoberta = Conta("Roberta", 2000);

    List<Conta> contas = <Conta>[contaMatheus, contaRoberta];
    
    print(contaMatheus.titular);
}

// código omitido

Após salvarmos o arquivo, podemos abrir nosso terminal e executar o dart run.

Build anybank:anybank.

Matheus

Legal. Nosso terminal trouxe o nome do titular, que é "Matheus". Agora chamaremos o saldo. Ao final do primeiro print(), pressionaremos "Enter" e, abaixo da linha, escreveremos print(contaMateus.saldo);. Salvamos nosso arquivo e rodamos novamente o dart run no terminal.

void main() {
    Conta contaMatheus = Conta("Matheus", 1000);
    Conta contaRoberta = Conta("Roberta", 2000);

    List<Conta> contas = <Conta>[contaMatheus, contaRoberta];
    
    print(contaMatheus.titular);
    print(contaMatheus.saldo);
}

// código omitido

Build anybank:anybank.

Matheus

1000.0

Apareceu "Mateus" e "1000.0" no terminal. Agora conseguimos visualizar e acessar cada uma das variáveis.

Alterando os valores das variáveis

Para alterar o valor, ao final da linha print(contaMatheus.saldo);, pressionaremos "Enter" duas vezes. Ainda dentro do escopo da main(), acessaremos uma conta, dessa vez a da Roberta. Começaremos acessando o saldo, então escreveremos contaRoberta.saldo.

Queremos alterar esse saldo, por exemplo, modificar de 2000 reais para 5000 reais. Do mesmo jeito que atribuímos um valor a uma variável usando o sinal de igual (=) para atribuição, podemos usar a mesma estrutura para mudar a propriedade de uma classe. Informamos qual propriedade queremos acessar, falta passar o novo valor dela, usando o sinal de atribuição: contaRoberta.saldo = 5000;.

void main() {
    Conta contaMatheus = Conta("Matheus", 1000);
    Conta contaRoberta = Conta("Roberta", 2000);

    List<Conta> contas = <Conta>[contaMatheus, contaRoberta];
    
    print(contaMatheus.titular);
    print(contaMatheus.saldo);
    
    contaRoberta.saldo = 5000;
}

// código omitido

Para descobrirmos se deu certo, imprimiremos o valor do saldo da Roberta antes dessa modificação. No começo da linha contaRoberta.saldo, pressionaremos "Enter" duas vezes, deixando um novo espaço de duas linhas para cima.

Subiremos duas linha e escreveremos o print() do titular e do saldo da Roberta. Em seguida, após a modificação, também pressionaremos "Enter" duas vezes, descendo duas linhas. Novamente pediremos para imprimir o saldo da contaRoberta.

void main() {
    //código omitido
    
    print(contaMatheus.titular);
    print(contaMatheus.saldo);
    
    print(contaRoberta.titular);
    print(contaRoberta.saldo);
    
    contaRoberta.saldo = 5000;
    
    print(contaRoberta.saldo);
}

Salvamos o código e voltamos para o terminal, onde executaremos o dart run.

Build anybank:anybank.

Matheus

1000.0

Roberta

2000.0

5000.0

Apareceu o nosso print() do Mateus, com 1000 reais. Depois, Roberta, com 2000 mil reais, ou seja, o valor que atribuímos no começo. Abaixo dos 2000 foi quando fizemos a modificação e apareceu a alteração do saldo, para 5000 mil reais. Portanto, apareceram essas mudanças.

Observação sobre alteração de variáveis

Então aprendemos a estrutura para acessar e modificar as propriedades de uma classe: nomeDaClasse.nomeDaVariável. Se quisermos alterar, basta adicionarmos o sinal de atribuição (=) e passar o novo valor.

Só um ponto importante é que não podemos passar um tipo de valor diferente. Por exemplo, o saldo foi definido como double, então não podemos passar uma string como novo valor.

Se substituirmos o 5000 pela string "5000", a IDE já avisa que tem um erro. Passando o cursor por cima, abrimos uma mensagem em inglês que informa:

O valor do tipo 'String' não pode ser atribuído a uma variável do tipo 'double'.

Portanto, podemos alterar os valores das variáveis, mas não o tipo delas.

Imprimindo as contas

Agora, com nossas contas criadas, podemos imprimir todas essas contas. Fizemos isso através do método print(), recebendo o titular e o saldo tanto da contaMateus, quanto da contaRoberta.

Entretanto, podemos substituir essas linhas de código por um laço de repetição do Dart, no caso, o laço for(){}. Escreveremos esse laço dentro da função main(), no lugar das linhas de print() que criamos. Nos parênteses, passaremos (Conta conta in contas) e, nas chaves passamos o que vamos imprimir: print(conta.titular); e print(conta.saldo);.

void main() {
    Conta contaMatheus = Conta("Matheus", 1000);
    Conta contaRoberta = Conta("Roberta", 2000);

    List<Conta> contas = <Conta>[contaMatheus, contaRoberta];
    
    for (Conta conta in contas) {
        print(conta.titular);
        print(conta.saldo);
    }
    
    contaRoberta.saldo = 5000;
    
    print(contaRoberta.saldo);
}

Com esse laço de repetição, para cada conta que tivermos dentro da lista contas, acessaremos a propriedade titular e a propriedade saldo dessa conta. Agora não importa de temos a contaMatheus, a contaRoberta ou outras contas, o laço imprimirá as informações de todas elas.

Vamos visualizar isso. Após salvarmos o código, abriremos o terminal e rodaremos o dart run.

Build anybank:anybank.

Matheus

1000.0

Roberta

2000.0

5000.0

Recebemos o nome do titular e o saldo da contaMatheus e da contaRoberta. No final, ainda recebemos o saldo de Roberta após a modificação.

Com isso, terminamos nossas tarefas: guardar as informações da conta (titular e saldo) e relacioná-las em um único conjunto de informações.

Sobre o curso Dart: trabalhando com orientação a objetos

O curso Dart: trabalhando com orientação a objetos possui 117 minutos de vídeos, em um total de 53 atividades. Gostou? Conheça nossos outros cursos de Flutter 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 Flutter acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas