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".
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.
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.
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.
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.
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.
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];
}
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.
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);
}
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()
.
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
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
.
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.
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
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.
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.
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.
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.
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:
Impulsione a sua carreira com os melhores cursos e faça parte da maior comunidade tech.
1 ano de Alura
Assine o PLUS e garanta:
Formações com mais de 1500 cursos atualizados e novos lançamentos semanais, em Programação, Inteligência Artificial, Front-end, UX & Design, Data Science, Mobile, DevOps e Inovação & Gestão.
A cada curso ou formação concluído, um novo certificado para turbinar seu currículo e LinkedIn.
No Discord, você tem acesso a eventos exclusivos, grupos de estudos e mentorias com especialistas de diferentes áreas.
Faça parte da maior comunidade Dev do país e crie conexões com mais de 120 mil pessoas no Discord.
Acesso ilimitado ao catálogo de Imersões da Alura para praticar conhecimentos em diferentes áreas.
Explore um universo de possibilidades na palma da sua mão. Baixe as aulas para assistir offline, onde e quando quiser.
Acelere o seu aprendizado com a IA da Alura e prepare-se para o mercado internacional.
1 ano de Alura
Todos os benefícios do PLUS e mais vantagens exclusivas:
Luri é nossa inteligência artificial que tira dúvidas, dá exemplos práticos, corrige exercícios e ajuda a mergulhar ainda mais durante as aulas. Você pode conversar com a Luri até 100 mensagens por semana.
Aprenda um novo idioma e expanda seus horizontes profissionais. Cursos de Inglês, Espanhol e Inglês para Devs, 100% focado em tecnologia.
Transforme a sua jornada com benefícios exclusivos e evolua ainda mais na sua carreira.
1 ano de Alura
Todos os benefícios do PRO e mais vantagens exclusivas:
Mensagens ilimitadas para estudar com a Luri, a IA da Alura, disponível 24hs para tirar suas dúvidas, dar exemplos práticos, corrigir exercícios e impulsionar seus estudos.
Envie imagens para a Luri e ela te ajuda a solucionar problemas, identificar erros, esclarecer gráficos, analisar design e muito mais.
Escolha os ebooks da Casa do Código, a editora da Alura, que apoiarão a sua jornada de aprendizado para sempre.