Transcrições
1. Introdução: Olá. Bem-vindo
ao meu curso sobre Java. Agora, se você clicar neste curso, provavelmente terá pelo menos
uma vaga ideia do que
é Java e que, de alguma forma, é importante para sua carreira e
sua educação Bem, você não está errado.
Deixe-me mostrar como Java é uma das linguagens de
programação mais populares do mercado, usada por praticamente
todas as empresas de tecnologia Praticamente a página de carreiras de qualquer
empresa de tecnologia listará o Java como
uma das habilidades. Saber programar é
a habilidade que o
coloca no caminho certo para obter
um salário muito generoso. O motivo é que o Java
é eficiente, rico em recursos e relativamente fácil de
aprender em comparação com outras linguagens
, como C. Isso
também significa que você pode aprender a
programar sem
passar por um curso de uma semana Os fundamentos do Java podem ser resumidos em apenas algumas horas, que é o que eu
fiz neste curso Você usará as lições
deste curso para criar seu próprio
jogo interativo que
poderá compartilhar com seus amigos
ou colocar em seu currículo. Uma coisa que os recrutadores
buscam são projetos pessoais
verificáveis, e esse se encaixa Você pode optar por fazer todo
o projeto sozinho se
quiser desafiar. Como alternativa,
também incluí quatro vídeos explicativos. Ajude-o
caso de você se perder. Também configurei
todas as amostras de código em um ambiente sandbox on-line.
Agora, o que isso significa? Isso significa que não há
necessidade de computadores complexos. Sem instruções misteriosas de configuração. Tudo o que você precisa fazer
é visitar os links que eu forneço e clicar
no botão verde Executar. Você pode gastar toda sua
energia se concentrando
na codificação real em vez de perder tempo configurando
um ambiente de codificação Espero que você esteja empolgado
em aprender sobre Java. Passo muito tempo preparando este curso e
espero que apareça. Te vejo no próximo vídeo.
2. Sobre você e eu: Olá. Neste vídeo, falaremos brevemente sobre o público-alvo
deste curso, bem
como por que você deve
escolher esse curso dentre todos os cursos disponíveis que você provavelmente vê por aí. Então, primeiro, por que você
deveria confiar em mim? Você nem me conhece bem. Eu trabalho para uma das
maiores empresas de tecnologia do mundo que
atualmente está sediada em Cupertino Eu realmente não tenho permissão
para dizer para quem trabalho. Mas basta dizer aquele código
publicitário que impactou as experiências
de usuário de milhões de pessoas,
talvez até a Tenho muita experiência em
escrever códigos que importam. Antes de trabalhar
na indústria de tecnologia, eu realmente
ensinei ciência da computação na Universidade da Califórnia,
Berkeley, por O curso que ministrei C 61 foi nomeado um dos cinco
melhores cursos nos Estados Unidos
pela Bloomberg e regularmente mais de 2.000
alunos a cada semestre Também gravei
vídeos do Youtube para esse curso no canal
CS 61, um departamento Em agosto de 2023, esse canal recebeu
mais de 963.000 visualizações Finalmente, em 2020,
fui nomeado um
dos 13 melhores instrutores
do departamento de engenharia da universidade De várias
centenas, tenho
muita experiência ensinando e
gerenciando turmas grandes, especialmente aquelas
com um componente
on-line significativo como este. Agora, por que ele deveria
escolher essa classe? Bem, eu mencionei isso
em um vídeo anterior, mas uma
vantagem significativa desse curso é
que todo o código é público e Agora, você pode não entender o que isso significa ou
por que é significativo, e isso é totalmente razoável. Basicamente, um problema
que geralmente ocorre nos cursos de
programação
é que, mesmo que você pegue o código do instrutor exatamente como está e o
coloque no seu computador, talvez
você não obtenha
a mesma saída ou talvez o código
nem seja executado O motivo é que os computadores
são máquinas muito complexas. Muitas vezes, seu computador
pode não estar configurado exatamente da mesma forma que o
computador do instrutor está configurado Neste curso, todo o código foi movido para um ambiente
on-line, incluindo o código do projeto. Toda a configuração da codificação
foi
abstraída para você e
cuidada para que
você possa concentrar toda
a sua energia na
programação, em vez de
configurar o computador Se você quiser acompanhar este curso de
forma interativa, recomendo que você crie
uma conta na Repl Vou colocar um link na descrição
do curso , bem como nos recursos. Em seguida, quero
falar brevemente sobre o público-alvo
do discurso Agora, não se assuste
com essa afirmação. Mesmo que você não tenha nenhuma
experiência em programação, você ainda deve ser capaz de
tirar muito proveito dessa classe Dito isso, se você realmente quiser cobrir todas as suas bases e ter
certeza de que entendeu toda a sintaxe
Java de baixo para cima, recomendo que dê uma
olhada no meu outro curso, Java for Beginners
Code em 1 hora Essa aula
ensinará alguns detalhes
essenciais sobre
programação No entanto, você não precisa saber tudo dessa classe para entender as coisas
dessa classe. O que eu recomendo que você faça é
assistir a alguns vídeos
desta aula e ver se você entende o significado
do que estou dizendo. Se descobrir que você
não entende nada, recomendo que faça uma pausa. Confira alguns vídeos
do curso que eu filmei anteriormente e volte para esta
aula quando estiver pronto E isso é tudo para este vídeo. Na próxima vez que você me ver,
vamos entrar em
algum conteúdo real
3. Apresentação do projeto: Bem-vindos amigos. Neste
vídeo, falaremos sobre o projeto
que você
implementará ao longo deste curso. O projeto que vamos implementar
se chama Minesweeper Sinta-se à vontade para pesquisá-lo
no Google, pois é um jogo muito popular e
não é exclusivo dessa classe. Mesmo que você já esteja
familiarizado com o jogo, eu ainda recomendo que
você
assista a este vídeo para entender nossa implementação
específica. O código do
projeto que você
receberá foi
parcialmente concluído, mas faltam algumas partes
importantes. Seu objetivo será corrigir esses
componentes essenciais para que o jogo funcione da mesma forma
que neste vídeo. Examinaremos
esses componentes
juntos em pontos
posteriores do curso para que você não se perca. No final do projeto,
você poderá jogar o jogo de forma interativa e
convidar seus amigos e familiares para jogar também Agora vamos ver como
esse jogo funciona. Vamos clicar em
Executar nosso jogo mental. Sweeper começa com um tabuleiro de dez por
dez de células inexploradas. Todas essas células, marcadas com X são células que ainda
não foram reveladas. Essas células, com letras de a J nas
bordas do quadro, ajudam você a identificar
as coordenadas de uma célula Nossas coordenadas
terão a coluna de linha do formulário. Por exemplo, essa
célula aqui terá coordenadas
porque está em A.
Na coluna B, todas as células
são células numéricas, células vazias ou células minadas, mas seu estado está
atualmente oculto pelo X. Se você tocar em uma célula que é uma célula mina, você perde o jogo O objetivo do jogo é
encontrar todas as células não minadas. Vamos ver o que acontece
quando tocamos em uma célula. Podemos fazer o toque B, ok? Foi
revelado que B é uma célula vazia, o que podemos ver porque,
bem, está vazia. Uma célula vazia é aquela que tem zero minas imediatamente
adjacentes a ela Isso significa que a célula A, a célula B, a célula A AC, a célula BC e a célula BB não eram minas. Isso significa que todos
eles estavam seguros de usar. Observe que depois de
gravarmos a célula B, várias outras células
também foram reveladas Tudo isso aqui,
todas essas células vazias bem
como essas
células numéricas aqui. Fazemos isso porque,
como acabei de dizer, uma célula vazia significa que todas as células adjacentes a essa célula
vazia podem ser acessadas com segurança. Basta tocar neles para
que você economize tempo. Se encontrarmos uma célula vazia
adicional ao lado da célula
vazia original que gravamos, também
tocaremos em todas as células seguras ao redor dessa célula E continuamos
esse processo até
ficarmos sem células seguras para acessar. Vamos dar uma olhada
nessa célula, por exemplo. Esta célula foi revelada
como sendo uma célula numérica. O número dois significa
que há exatamente duas células de mina
imediatamente adjacentes a ela. Isso significa que essas células são todas potencialmente células mineiras. Esta também é
potencialmente uma célula de mina. Como podemos descobrir
qual é seguro ou não? Este é o ponto crucial do jogo
do varredor de minas. Precisamos combinar
informações de outras células para deduzir
informações para essa Aqui está uma maneira de deduzir
qual célula é uma célula de mina. Vamos dar uma olhada
nesta célula aqui. Também foi
revelado que essa célula é uma, mas como essas células ao redor dela já
foram reveladas
como células vazias, foi revelado que
ela é uma célula numérica, e esta foi revelada
como uma célula numérica. Só resta
uma célula adjacente a esta. Portanto, essa
célula não revelada deve ser a célula da mina. Como não queremos
tocar em uma mina, vamos sinalizar a célula como perigosa para que
saibamos que não devemos tocar nela. Podemos ver que esse
X aqui está na
linha e na coluna H.
Podemos fazer a bandeira F, H. Esse símbolo triangular nos
indicará que a célula está marcada e sabemos que
não devemos tocar nela Agora, como sabemos que
essa célula é uma célula de mina, sabemos que essa célula estará segura.
Por quê? Pause o vídeo e eu
revelarei a resposta em 321. A razão é que essa
célula numérica aqui é uma. Já deduzimos que essa era uma célula perigosa por causa
desse número um aqui Portanto, como
já encontramos a única célula adjacente a essa
célula numérica que é uma mina, sabemos que todas as
outras células ao redor
dessa célula número um serão seguras de
serem acessadas. Vamos
testar nossa hipótese. Vamos tocar em I. Na verdade, vemos que foi
revelado que eu era uma célula numérica, seja, três que
era segura de tocar. Embora ainda existam muitas
minas nessa área,
na grande maioria dos casos, você poderá continuar
esse processo de inferência por todo
o tabuleiro e, eventualmente identificar onde estão todas
as minas Se você acha que cometeu um erro, também
pode desmarcar
a célula dessa forma Agora, H foi redefinido para uma célula não revelada
para fins de demonstração. Vamos ver o que acontece se
você tocar nessa célula da mina. Esses asteriscos
representam mentes em nosso tabuleiro e podemos ver que agora
terminamos o jogo Vamos reiniciar o jogo
clicando no botão Executar. Agora, vou percorrer a próxima placa muito rapidamente para que você possa ver o resultado final. Sinta-se à vontade para assistir a este vídeo em velocidades
muito lentas se
quiser acompanhar e ver se consegue
determinar por que
tomei a decisão de sinalizar ou
tocar em determinadas células. Finalmente, podemos ver que
exploramos todas as células não mineiras Nós vencemos o jogo no total. Cada jogo deve
ter dez células minadas. Ok, e
isso é tudo para este vídeo. Espero que isso deixe você
empolgado em fazer o projeto. Eu passo muito tempo preparando
isso para você e espero que você tenha aprendido
muito sobre Java fazendo isso. Te vejo no próximo vídeo.
4. Ilustração de herança: Bem-vindos, amigos. Neste vídeo, falaremos
sobre herança Para tornar esta lição
um pouco menos seca, falaremos
sobre sorvete. Isso é sorvete. Agora imagine que você
tem um amigo que nunca ouviu falar de sorvete e peça que você o descreva para ele. Cada unidade de sorvete vem com uma série
de características comuns. Por enquanto, vamos simplificar
e deve ser bastante seguro dizer que cada unidade de
sorvete tem creme. Uma temperatura de cerca de 0 graus Celsius e um cone para segurar o creme Agora imagine que você terminou descrever o sorvete para
seu amigo imaginário Mas agora ele está curioso sobre
diferentes tipos de sorvete,
como sorvete de morango
e sorvete de mirtilo Você provavelmente o
descreveria da mesma forma que descreve o
sorvete original aqui. Esses novos sabores também têm um cone e uma temperatura
de cerca de 0 graus Celsius A única diferença é que o sorvete de morango tem creme com sabor de
morango
e o sorvete de mirtilo tem creme com sabor de mirtilo Tudo isso é bom e elegante
para este exemplo em particular. Se tivermos apenas três atributos
para descrever o sorvete, não
faz mal
nos repetirmos para cada um, mas você pode imaginar
que talvez queiramos adicionar ainda mais características para
descrever esse sorvete. Talvez queiramos também adicionar
um atributo de sabor de cone ou uma textura de cone. Ou talvez o peso
do sorvete ou o volume do sorvete. Você pode obter infinitamente mais
descrições sobre o sorvete. E toda vez que seu amigo pedisse que você descrevesse um novo sorvete com
sabor, você precisaria
redefinir cada uma dessas características
repetidamente Seria muito bom se
tivéssemos uma maneira de reduzir
a quantidade de trabalho que
temos que fazer para descrever
novos sabores de sorvete É aqui que a herança
entra naturalmente. Em algum momento,
você se cansaria de descrever as mesmas
características do sorvete. Em vez de reiterar que o
sorvete tem uma casquinha e uma temperatura de 0 graus Celsius,
você diz ao seu amigo, bem, o sorvete de mirtilo é
igual ao sorvete normal, exceto que o creme
tem um sabor diferente, resto é A herança é um paradigma em Java que nos permite fazer Herança significa que os
comportamentos e atributos de um modelo básico são copiados para
um modelo mais novo Ainda temos a
capacidade de sobrescrever atributos
selecionados, como o sabor do
creme, nesse caso Então, isso é incrível agora, em vez de
nos repetirmos e redefinirmos cada atributo de sorvete quando definimos um novo sabor de
sorvete, tudo o que precisamos fazer é
substituir um atributo,
o atributo sabor do creme, e herdar o resto dos atributos compartilhados
do modelo básico de sorvete,
como
a temperatura
e a casquinha Isso parece muito simples, mas é um
princípio muito importante da programação Java Reduzir o código repetitivo
é muito importante para recapitular. Herança é como
maximizamos o código, reutilizamos e simplificamos Mostrarei alguns
exemplos concretos de como isso se parece em código
no próximo vídeo.
5. Exemplos de herança: Olá amigos. Neste vídeo, discutiremos
alguns exemplos concretos de
herança. Primeiro, imagine que temos uma classe chamada dog e digamos que ela tem um campo
estático chamado sound e um método get chamado
get Sound que
recupera o som caso você tenha esquecido ou não esteja familiarizado
com a Eu recomendo que você pause
o vídeo agora e assista
ao vídeo intitulado Objetos
parte dois na minha outra aula, Java, para iniciantes em 1 hora Agora temos ainda outra
classe chamada Brown Dog, que amplia a classe de cães. Essa sintaxe estendida é nova. É assim que especificamos padrões de
herança em Java. Nesse caso, diríamos que o cachorro marrom herda do cachorro Não se preocupe com as
implicações disso por enquanto. Basta reconhecer o Dysntex. Agora, digamos que o cachorro marrom tenha um método chamado get color, que simplesmente retorna
a palavra marrom. Agora vamos juntar tudo isso. Temos a classe
de cães de antes e temos a classe de cães marrons que
estende os cães em nossa classe principal. Vamos criar uma instância
da classe cachorro e uma instância
da classe marrom. Assim, se imprimirmos dog get sound e brown
dog getcolor, a saída é bastante
previsível. Cachorros entendem som. Vamos apenas imprimir latido
e marrom dog getcolor, vamos imprimir a palavra marrom A mágica acontece quando
fazemos bunda marrom para cachorros. Com base no que sabemos
até agora sobre programação Java, parece que isso
falharia, certo? Como a classe de cães pardos não tem um método de
obtenção de som, parece uma suposição
razoável. Acontece que,
se você executar isso,
essa última declaração
na verdade imprimirá latido. O motivo é que temos herança quando uma
classe estende outra, Java primeiro examinará
a classe estendida e verá se ela tem um método ou campo
definido, caso contrário O Java então verifica
sua classe mãe. Nesse caso, primeiro verificamos o método
get sound em
brown dog. Ele não tem esse método, então verificamos que o cão da classe
parental tem o método get sound. Use esse método
que retorna a casca. Quero enfatizar
aqui que o Java usará o
método mais específico encontrado primeiro. Lembre-se de que Java
olha
primeiro para o cachorro marrom para obter o som
antes de olhar para o cachorro. Isso significa que se o cachorro marrom tivesse um método de obtenção de som que
retornasse algo diferente do método cães obtivesse som e chamamos de
cachorro marrom, cachorro, obtenha som. Java teria usado
o método get sound vez disso, Java teria usado
o método get sound
definido em brown dog. Isso foi um bocado.
Se você está assistindo na velocidade de
1,5x ou 2x
e não entendeu,
recomendo que você retroceda 30 segundos e ouça
a frase novamente. Em uma velocidade X, esse é o fim da nossa discussão
sobre herança Para recapitular, usamos a palavra-chave
extends para
dizer ao Java que gostaríamos de
criar uma relação de herança Depois que a relação de herança é
estabelecida, Java usa a resolução dinâmica de
métodos para descobrir qual
método usar Primeiro, ele examina
a classe real da qual
estamos chamando o método. E somente se o método estiver ausente o Java aparecerá
na classe mãe Aqui está o link para
o código de repelência, usando esta lição para
você mexer Te vejo no próximo vídeo.
6. Super exemplos: Bem-vindos amigos.
Neste vídeo, falaremos sobre a superlembrança da
lição anterior de que tivemos uma aula de cães que tinha
um método de obtenção de som. Também tínhamos uma
classe de cães pardos que, herdada cães
pardos, tinha
um método de obtenção de cores Quando chamávamos o
cachorro marrom de obter som, cachorro
marrom reusava o método de obtenção de som de
um cachorro por herança Além disso, lembre-se da ordem na qual o Java resolve os nomes dos métodos Se chamarmos de marrom, ouça o som. Java procuraria primeiro obter som
na classe
Brown Dog. Java só apareceria
na classe de cães se cachorro
marrom não
tivesse o Sound. Se brown dog tivesse
um método get sound definido e chamássemos
brown dog get sound, brown dogs get sound
substituiria o
método get sound da classe dog O que significa que
executaríamos a lógica contida em
cachorro marrom em vez de cachorro. Podemos
reutilizar, ou substituir métodos
da classe principal Mas e se quisermos substituir e reutilizar a lógica
da classe principal Vamos ver como isso funciona. Primeiro, digamos que tenhamos
nossa aula de cães novamente, método
get sound
que retorna latido. Agora, digamos que temos nossa classe de cães
pardos, que herda de cães e também
tem um método de obtenção de som Esse método tem uma nova palavra-chave que nunca vimos antes. Super. Super é como referenciamos a
classe principal da classe atual. Nesse caso, super é na verdade
um apelido para a classe de cães. Isso significa que o super
do get sound é análogo a dizer que o
cachorro obtém o som O que significa que o
som super get retornará o latido. O resultado de todo esse método
marrom de dogtetsund será casca É basicamente
isso. Aprendemos sobre nossa nova palavra-chave super, que é usada para se
referir a uma classe principal quando escrevemos código
dentro da classe secundária. Essa palavra-chave também nos permite
criar métodos híbridos de substituição Isso quer dizer que podemos
reutilizar o código da classe principal e também adicionar nossa
própria lógica personalizada. Aqui está o link
para o código de
repelência desta lição para
você mexer Te vejo no próximo vídeo.
7. Polimorfismo de subtipo: Neste vídeo,
falaremos sobre polimorfismo de subtipo Antes de começarmos,
por favor, não se deixe intimidar por essas palavras que soam muito
sofisticadas Na verdade, o conceito não é muito mais complicado do que
qualquer coisa que vimos até agora, mas os designers de Java não
conseguiram criar
um nome mais simples Mais uma vez, vamos começar
nossa ilustração com uma classe de cães que tem um método get sound
que retorna latido. Também teremos uma
classe de cães pardos que herda de cães, e esse método de cães marrons
retorna latidos marrons Juntando tudo isso,
temos nossas duas classes. Temos um terceiro método de obtenção de
som localizado
em nossa classe principal. Esse terceiro método usa
uma instância de cachorro e simplesmente chama esse método de obtenção de som
para cães. Se instanciarmos uma instância
da classe base dog e, em seguida, passarmos essa classe base para esse método como
seria de esperar, obteríamos bark como saída Mas agora digamos que instanciamos uma instância brown dog e passamos esse objeto para
esse método get sound Isso é estranho. O método get sound
aqui no canto inferior direito aceita apenas
argumentos do tipo
dog, mas o tipo de objeto que estamos
transmitindo é brown dog. Com base no que sabemos sobre Java, parece que
deveria dar um erro, certo? Acontece que isso não
será um erro. Na verdade, essa linha
imprimirá uma casca marrom. Isso se deve a algo em
Java chamado método dinâmico resolução é um exemplo
de polimorfismo de subtipo polimorfismo de subtipo basicamente
significa que um subtipo de um tipo pode ser
tratado como um tipo pai Intuitivamente, isso
deve fazer sentido. Um cachorro marrom deve ter todas
as propriedades de um cachorro. Um chihuahua marrom deve ter todas as propriedades
de um Uma coisa mais específica
deve ter pelo menos todos os comportamentos e características de uma coisa relacionada menos
específica. Agora, voltando a este exemplo, a razão pela qual podemos passar um cachorro marrom para
esse método que aceita tipos de cães é que Java assume
tipos específicos de cães será capaz de
chamar todos os métodos
da classe base de cães quando o
programa for realmente executado O Java então resolverá os métodos de
instância usando o tipo
dinâmico de um objeto. Também conhecido como o tipo de
objeto, na verdade, é um cachorro marrom e não
o tipo estático que
declaramos que seja
neste método dog Vou dizer isso mais uma vez
porque é um conceito muito importante. O tipo estático de
um objeto é o que declaramos explicitamente como objeto Nesse método, é cachorro marrom. Nesse método, o
tipo estático muda para cão. O tipo dinâmico de
um objeto é
o que o objeto realmente é
e nunca muda. Nesse caso, o
tipo dinâmico é cachorro marrom. Para resolver um método de instância, usamos o
tipo dinâmico do objeto. Você pode estar se
perguntando por que fazemos isso. Por que diabos nos
confundiríamos? Por que não chamá-lo
de cachorro marrom quando o
instanciamos e o
mantemos como cachorro marrom A razão pela qual
talvez queiramos
reutilizar esse método para
muitos tipos de cães. Imagine que, além
da classe de cães pardos, também
tivéssemos classes de cães brancos, cães azuis e cães
amarelos, todas herdadas de cães e todas com métodos sólidos Seria muito
irritante se tivéssemos que
definir um método que aceita um objeto do tipo cachorro marrom e outro método que aceita
um objeto do tipo cachorro branco, cachorro amarelo
e cachorro azul Quando todos esses métodos
fazem exatamente a mesma coisa, em vez de nos repetirmos, criamos apenas um método que aceita o tipo de cão
do modelo básico Ao ter um tipo de entrada mais
geral, podemos maximizar nossa
reutilização de código e ter apenas um método que cuida de todos os casos mais específicos É isso para este vídeo. Para recapitular, falamos sobre polimorfismo de
subtipo. É um paradigma Java
que nos permite tratar instâncias
específicas de um objeto como um objeto base menos específico Também falamos sobre tipos estáticos
versus tipos dinâmicos, que ditam a forma como
resolvemos métodos de instância Ao nos referirmos a
um método de instância, usamos o método definido
no tipo dinâmico de um objeto
em vez do tipo estático. Aqui está o link
para o código de
repelência desta lição para
você mexer Nos vemos no próximo vídeo.
8. Ilustração abstrata: Bem-vindos amigos. Neste vídeo, apresentaremos uma visão geral visual das classes
abstratas. Nesta ilustração,
na verdade, voltaremos aos nossos exemplos de sorvetes
da aula de ilustração de herança. Lembre-se de que temos uma aula de
sorvete e também morango e sorvete aulas de sorvete de
morango e sorvete de
mirtilo
que herdam do sorvete Agora, se você pensar consigo mesmo, como são essas três classes
na vida real? Você provavelmente pode ter
uma ideia de é o
sorvete de morango e mirtilo Mais ou menos, eles se
parecem com isso. Essas aulas
refletem a realidade e estão ancoradas em exemplos
concretos Mas e a aula
de sorvete? Qual é a aparência de um
sorvete sem sabor? Você pode estar pensando em sorvete
de baunilha, mas até baunilha é um sabor. sorvete de baunilha também seria uma subclasse herdada da classe
de sorvetes Mas o sorvete em si, sem sabor, não
existe, pelo
menos não na mercearia
local Em Java, na verdade,
modelaríamos essa
classe de sorvete como um resumo. Uma classe abstrata é algo que não pode
ser instanciado diretamente porque uma instância desse objeto não
faz nenhum sentido Assim como um sorvete
sem sabor não faz sentido. Em vez disso, só podemos instanciar subclasses
de uma classe abstrata, como sorvete de morango ou
mirtilo Mais uma vez, estamos adicionando complexidade ao seu
trabalho e conhecimento. Parece que tudo o que estamos fazendo é limitar sua funcionalidade E você pode estar
se perguntando, por quê. Por que criaríamos
uma classe abstrata que nem pode ser instanciada Não estamos deliberadamente nos
limitando e diminuindo a velocidade
se nos forçarmos a criar
uma subclasse antes de
usá-la para uma subclasse antes de
usá-la A resposta é que,
embora um objeto como sorvete
sem sabor não
tenha nenhum significado em si mesmo, ele ainda tem
valor de duas maneiras A primeira é que os padrões de
herança ainda são verdadeiros aqui Assim como com a herança
regular, podemos definir um valor de campo no objeto base e fazer com que
as subclasses herdem esse Mesmo que o
sorvete sem sabor não exista, ainda
podemos declarar que
sua temperatura é 0
Celsius e fazer com que todas as subclasses
herdem Isso deve fazer sentido,
pois não precisamos ter uma classe concreta de sorvete para
determinar sua temperatura. Podemos simplesmente dizer que, em geral, sorvete deve estar em 0 Celsius e definir isso na classe abstrata
básica A segunda maneira pela qual as classes abstratas ainda
são valiosas é que elas podem especificar um contrato
que as subclasses devem cumprir Por exemplo, podemos declarar que todo sorvete deve ter
um método definido que retorne a cor
do sorvete no modelo
básico de sorvete Esse método não será
definido porque
não existe uma cor para
todas as instâncias de sorvete. No entanto, o sorvete de
morango pode ter um
método de obtenção de cor que retorna rosa E o
sorvete de mirtilo pode ter um método de obtenção de cor
que retorna azul Se tivéssemos uma classe de
sorvete adicional que
não fornecesse uma implementação de get
color, Java falharia na compilação Isso é bom
porque não
queremos que nosso código seja
compilado, a menos que tenhamos certeza absoluta de que todas as instâncias
concretas de sorvete tenham uma cor definida para elas. Isso pode parecer um pouco
confuso, mas não se preocupe. Mostrarei exemplos de como isso funciona
no próximo vídeo. É isso para esta lição. Falamos sobre
classes abstratas e como elas são quase objetos pois não podem ser instanciadas
diretamente, mas podem fornecer um contrato
ou modelo para Veremos
exemplos concretos disso em breve. Te vejo no próximo vídeo.
9. Exemplos abstratos: Olá amigos. Neste
vídeo, veremos alguns exemplos do uso
de classes abstratas. E, na verdade, vamos
agitar as coisas hoje. Em vez de percorrer
slides e diagramas de código, vamos programar
de forma prática Obviamente, eu
recomendo fortemente que você acompanhe sua conta do Repel
It, se puder Caso contrário, não deixe de
visitar o link Repel. Depois que a lição terminar, bifurque-a e mexa no
código A primeira coisa que
vamos fazer é visitar Repl. no botão Criar repelência, escolha o modelo Java e nomeie suas classes
abstratas Repel. Agora que ela foi criada, a
primeira coisa que vamos
fazer é criar uma classe
abstrata de cães. Vamos fazer isso clicando no botão
de novo arquivo aqui e chamando-o de Java. A primeira coisa
que vamos fazer é criar uma classe abstrata de cães. A declaração de classe parece quase uma definição de
classe normal, exceto que vamos adicionar
o modificador abstrato O modificador abstrato
significa apenas que teremos pelo
menos um
método abstrato dentro dessa classe Vamos primeiro definir um atributo chamado pernas dormentes
e defini-lo como quatro Observe que esse não é
um campo abstrato. Isso não
existe. Somente métodos podem ser abstratos em Java. Intuitivamente,
deve fazer sentido o motivo definimos como atributo
em uma classe abstrata Lembre-se de que não
precisamos de um tipo específico de cachorro para nos dizer
quantas pernas um cachorro tem. Os cães em geral têm quatro patas. É seguro defini-lo aqui. Agora vamos definir um
método regular não abstrato chamado Get Sound, que retornará latido. Isso vai se
comportar exatamente como qualquer outro método não abstrato em uma classe regular.
Sem surpresas aqui. Agora, finalmente, vamos definir
um método abstrato. Vamos chamá-lo de obter
cor e não defini-lo. Novamente, isso deve fazer sentido. Faz sentido definir, obter som para cães em geral, porque os cães geralmente
emitem o mesmo som. Mas qual é a cor de um cachorro? Você não pode responder
isso sem ter uma instância concreta de
um cachorro à sua frente. Portanto, é um método
abstrato. Agora vamos criar uma nova classe, classe
regular, não
uma classe abstrata. E faça com que amplie nossa classe
abstrata de cães. Vamos chamar
esse cara de cachorro marrom. E vai
ampliar nossa aula de cães. Classe pública Brown. Observe que a sintaxe para estender uma
classe abstrata é a mesma para estender uma classe
não Aqui, forneceremos uma implementação concreta
do método abstrato get color. A cor de um
cachorro marrom deve ser marrom. Só vamos
devolvê-lo marrom. Além disso, vamos adicionar uma anotação de substituição
a esse método A anotação at override
é 100% opcional, mas é uma boa prática
incluí-la O motivo é que o Java
verificará, em tempo de compilação se o método que
você anotou está realmente
sobrescrevendo Exemplos em que isso seria
útil seriam quando
você estivesse digitado incorretamente, o método ou o método não existissem realmente
na classe principal É especialmente importante ao sobrescrever
métodos
abstratos porque os métodos abstratos não têm nenhuma lógica definida
na classe abstrata Queremos ter
certeza absoluta de que
fornecemos uma
implementação concreta para o método. Agora vamos
juntar tudo isso em nossa aula principal. Então, a primeira coisa que vamos
testar é instanciar um cachorro assim. Vamos
ver o que acontece. Olha, temos um erro. Diz que o cachorro é abstrato
e não pode ser instanciado. Isso faz sentido, porque,
como dissemos antes, classes
abstratas não podem
ser instanciadas diretamente Só podemos instanciar
suas subclasses. Agora, vamos tentar instanciar
um cachorro marrom, que herda a partir desse momento o código compilado
sem nenhum problema Novamente, isso não deveria
fazer sentido. Brown dog é uma subclasse
de uma classe abstrata. Agora vamos ver o que acontece
quando chamamos esses métodos. Primeiro, vamos renomear
esse cara para Brown Dog porque é um cachorro marrom Vamos primeiro dar uma olhada nas pernas dormentes de cachorro
marrons. Se você se lembra,
cachorro marrom com pontos dormentes deveria ser esse cara
aqui na classe de cães Como os campos não podem ser abstratos, numb legs agirá
exatamente da mesma forma que os atributos definidos em
classes regulares funcionarão Quando chamamos de brown
dog dot numb legs, Java primeiro examina
a classe brown dog para ver se existe um atributo
de pernas dormentes. Isso não acontece. Em seguida, ele olha para
a classe dos pais, depois olha para o cachorro e
vê que existem pernas dormentes Essa primeira linha deve
imprimir quatro. Vamos testá-lo. Na verdade, recebemos quatro de volta. Em seguida, vamos testar
algumas chamadas de método. Vamos ver o que
acontece quando chamamos cachorro
marrom ponto obter cor e cachorro marrom ponto obter cor
e cachorro marrom ponto obter cor. Som Como esperado,
cachorro marrom ganha cor e retorna marrom. Esse é o método que estava vazio na classe original de cães , mas foi substituído em
cachorro marrom, cachorro marrom, cachorro get Som foi o método que definimos
na classe de cães pais e aquele cachorro marrom não definiu explicitamente. Recapitulação rápida Cachorro marrom tem
cor, cachorro tem. Som. Podemos ver que os métodos
regulares agem exatamente
da mesma forma que costumavam. Se não existir
em Brown Dog. Em seguida, chamaremos o método
definido na classe principal. No entanto, obter cores também age de forma semelhante
às aulas regulares. Chamamos o método
definido na subclasse. Nesse caso, se tivéssemos
esquecido de substituir o método get color
da classe abstrata que brown
dog herda do Java, teríamos gerado um erro Vamos realmente ver o que
acontece se fizermos isso. Digamos que escrevemos incorretamente get
color assim e clicamos em run. Você vê que agora temos um erro. O cachorro marrom não é abstrato e não substitui o método
abstrato, adquire cor no cachorro Esse é um dos benefícios de usar as classes abstratas. Vemos nossos erros de antemão
antes mesmo de executarmos o código. É isso para este vídeo. Hoje, analisamos as classes
abstratas e
como implementá-las, bem
como alguns dos
erros que podem surgir quando você faz uso indevido de classes
abstratas Aqui está o link
para o código de repelência. Eu gostaria que você o
bifurcasse e mexesse no
código
10. Passo a passo 1: Bem-vindos amigos. Neste vídeo,
abordaremos
a primeira parte
desse projeto usando o que aprendemos
nas últimas lições. Se você quiser
acompanhar de forma interativa, precisará criar uma conta e
verificar seu e-mail O link para isso deveria estar
na descrição da aula e no vídeo
de introdução deste curso Se você não quiser
criar outra conta, tudo bem. É
claro
que eu recomendo fortemente
que você crie uma conta. A primeira coisa que você vai
querer fazer depois de criar uma conta é visitar bit dot lee, minesweeper skeleton O link também está na descrição do
projeto. Quando estiver nesta página,
clique no botão de bifurcação e ele deverá levá-lo para uma cópia
do código em sua conta Vamos dar uma olhada na
estrutura desse projeto. Tenha os arquivos, a célula da placa principal, célula
vazia, a célula mental
e a célula numérica. Muito do código no
Maine e no Board foi implementado para você
. Posteriormente, abordaremos algumas partes que
faltam em apresentações posteriores. Neste vídeo, vamos nos
concentrar nas classes de células. Como você já deve ter
adivinhado, uma classe de célula representa um dos quadrados
no jogo
Minesweeper Vamos dar uma olhada mais de perto. A classe cell é
uma classe abstrata. Ele declara um contrato para
outras classes seguirem e também fornece
alguns métodos padrão Cada classe de célula concreta deve implementar um método de duas strings, que é sua
representação de string no quadro, e um método tap que define o que acontece
quando a célula é tocada Também temos alguns
sinalizadores valores
padrão de false
e alguns métodos que devem ser compartilhados entre todas as
implementações que foram Sinalizar, executar, sinalizar, entorpecer as mentes dos
vizinhos e incrementar os vizinhos entorpecidos. Eu quero que você pense
sobre o seguinte. Por que esses métodos são abstratos e por que
esses métodos são concretos? Pausa o vídeo e
eu responderei em 321. Bem, se eu
perguntar como deve ser a aparência de uma célula em geral e caça-minas,
você poderia responder Você não pode. Uma célula está em branco. Se for uma célula vazia,
ela tem um número nela. Se for uma célula numérica e tiver um asterisco, se
for uma célula mental, você precisará de uma
implementação concreta de uma célula para determinar como deve ser sua
representação em sequência como deve ser sua
representação Da mesma forma, o comportamento do toque também depende do tipo de
célula da qual você está falando. Por exemplo, se você tocar em uma célula
mental, o jogo acaba. Mas se você tocar em uma célula vazia, nós apenas o ajudaremos a acessar todas
as células seguras vizinhas Por outro lado,
se eu perguntar se uma célula, independentemente de seu tipo, foi tocada, você pode responder a essa pergunta?
Sim, você pode. Independentemente do
tipo de célula, você pode responder se
uma célula foi tocada. Da mesma forma, os
comportamentos de sinalizar e dessinalizar em uma célula são os mesmos
em todas as classes de células, independentemente do tipo Ok, vamos começar a abordar esses dois comentários
na classe de células. Em primeiro lugar, vemos que um método de ouro
foi usado. Quando você tem um método que retorna o estado de um objeto, é uma dica de que você
deve observar os campos do objeto Nesse caso,
tocamos e estamos sinalizados. O que você acha que
esse método deveria retornar, dadas essas informações? Bem, devemos retornar tapped pois seu nome sugere
que ele
armazenará informações sobre
o estado de toque das células Em seguida, vamos dar uma olhada na bandeira. Ele retorna vazio. Não precisamos nos preocupar com o valor
de retorno. Em vez disso, esse
método vazio sugere que seu único propósito é
modificar o estado de um objeto Dado que queremos modificar
o estado do objeto, qual variável você acha que
devemos modificar Bem, devemos modificar
o campo sinalizado, definindo seu valor Da mesma forma, o método
não sinalizado definirá o campo
sinalizado Isso é tudo que temos que
fazer para a classe de células. Vamos para a célula vazia. Primeiro, vemos que precisamos
substituir todos os métodos abstratos Vamos copiar os métodos
abstratos e começar a implementá-los. Vemos aqui que há
um comentário para usar esse caractere especial
para células sinalizadas Vamos começar
implementando essa lógica. Como você sabe se
uma célula foi grampeada? Bem, vamos dar uma olhada. Temos essa
variável sinalizada que armazena informações sobre o estado da
bandeira da célula. Vamos usar isso. Se essa célula foi marcada, retornamos esse
caractere especial aqui Caso contrário, se essa
célula tiver sido tocada
, retornaremos um espaço vazio Por ser uma célula vazia, se você tocar em uma célula vazia, ela deverá revelar um espaço vazio. Finalmente, se essa célula
não foi sinalizada nem tocada, como
ela deveria ser Bem, lembre-se de
nosso primeiro vídeo falando sobre esse projeto, dissemos que todas
as células começam como um X, o que
simplesmente representa isso, esse estado celular ainda
não foi revelado. seguir, vamos dar uma olhada, como o nome sugere, o que você acha que esse
método vai fazer? Vídeo positivo, e
eu responderei em 321. O método principal
definirá o campo tocado como
verdadeiro para que possamos lembrar
o estado dessa célula Depois de definir o sinalizador como verdadeiro, notamos que esse método
precisa retornar um ouro Bem, na verdade, é muito
difícil dizer aqui se
precisamos retornar verdadeiro ou
falso. Vou te dar uma dica. Se você quiser desafiar, experimente visitar o Board Java e
veja o método tap. Veja se você pode deduzir qual
deve ser
o valor de retorno pretendido
do método tap das classes de células em um toque bem-sucedido E pause o vídeo se
quiser pensar sobre isso. Se não, vou
te dar a resposta. A resposta está em 321, retornaremos verdadeiro, pois um valor de retorno verdadeiro indica que
era seguro tocar na célula O que podemos deduzir
observando o Board dot Java. Vemos no Java integrado que,
se o resultado do toque for verdadeiro, continuaremos procurando células vazias
vizinhas para tocar Em outras palavras, um resultado de toque verdadeiro significa que
era seguro tocar na célula. Caso contrário, não procuraríamos células
vazias vizinhas
para tocar Agora vamos passar para
a célula numérica e
repetir o exercício. Desta vez,
queremos substituir
os métodos abstratos e
também entorpecer as mentes dos vizinhos O método de toque será praticamente o
mesmo da célula vazia. Também é seguro tocar em uma célula numérica. Nós nos tornamos verdadeiros e transformamos
as barras de torneira em verdadeiras. O método de duas strings
também será muito semelhante
ao método de
duas strings das classes anteriores exceto que, se tiver sido tocado, devemos retornar o número de minas
vizinhas a essa célula Convenientemente,
vemos que há um campo chamado mentes
vizinhas entorpecidas Não se
preocupe muito com a forma como usamos esse método para incrementar os vizinhos
Numb mas saiba que já
implementamos isso para Basicamente,
chamamos esse método
no momento apropriado ao
plantar minas no tabuleiro O vizinho numb Minds
nos fornece o valor correto. Como queremos que esse método
retorne uma string, Numb Neighbor Minds,
como um número inteiro, precisamos converter esse
inteiro Mas como fazemos
isso? Bem, vamos usar um
recurso fantástico chamado Google. Vamos pesquisar em Java como
converter um inteiro em uma string. Vamos clicar
no primeiro resultado. Vamos rolar um pouco para baixo e vemos imediatamente
que há um exemplo aqui, I é igual E convertemos esses dez em uma
string usando o valor da string. Vamos
usar esse valor de fluxo desse número
de mentes vizinhas. Dessa forma, esse valor de retorno corresponde ao valor
de retorno do método de duas cadeias de caracteres. Finalmente, vamos também ignorar as mentes
entorpecidas dos vizinhos, o que não precisávamos fazer na
aula anterior Numb Neighbor Minds,
como o nome sugere, retorna o número de minas
que são células vizinhas Temos um campo que
retorna exatamente isso. Vamos voltar às mentes
dos vizinhos. Agora completamos
a célula numérica. Vamos dar uma
olhada na aula final que estamos implementando
neste vídeo. Na verdade
, a célula mental terá muitas semelhanças com as
células anteriores que acabamos de implementar Vamos copiar
esses métodos abstratos. O
método de captura de células mentais será diferente
das aulas anteriores. Ainda vamos definir
o campo tocado como verdadeiro, mas em vez de retornar verdadeiro, retornaremos falso Como verdadeiro significa que
foi uma torneira segura, uma mina não é uma
célula segura para se tocar. O
método de duas cadeias de caracteres será
semelhante a outras classes, exceto que, se for tocado, devemos retornar um asterisco porque essa é sua
representação no quadro Na verdade, isso é tudo que
precisamos fazer agora. Terminamos com todas as
nossas aulas de celular. Na verdade, não poderemos
verificar se fizemos isso corretamente até o
final de todas essas orientações. Como desafio, se você
quiser ver se realmente entendeu o que estava
acontecendo neste vídeo, recomendo que você bifurque o código
original e veja se consegue preencher todos os
comentários sobre tarefas no esqueleto
sem minha ajuda Caso contrário, nos
vemos no próximo vídeo.
11. Interfaces: Bem-vindos amigos. Neste vídeo , falaremos
sobre interfaces. Mas espere, nós
nem falamos sobre interfaces antes.
O que eles são? Interfaces são
classes que especificam um contrato e não podem ser
instanciadas diretamente. Agora eu sei o que você está pensando. Isso não soa exatamente como a definição que demos
para classes abstratas? Você realmente estaria correto. As interfaces são muito semelhantes às classes
abstratas e sua
funcionalidade fundamental é a mesma. Agora você provavelmente está
se perguntando por quê. Por que temos essas entidades em Java que praticamente
fazem a mesma coisa? É quase como se os designers da
linguagem Java estivessem
tentando nos enganar. Bem, acontece que
existem algumas diferenças entre classes abstratas e interfaces. Vamos examiná-los. A maior diferença é que as classes
abstratas
suportam apenas herança única, enquanto as interfaces suportam
várias Em Java, uma classe só pode
herdar de, no máximo, uma classe que inclui classes
abstratas Um cachorro marrom pode herdar de um cachorro, mas não poderíamos fazer cachorro
marrom herdasse
de outra coisa,
como, digamos, um
animal marrom, por As interfaces
contornam esse problema. As interfaces não são herdadas
como as classes. Em vez disso, eles são implementados e uma classe pode implementar
várias interfaces. Em nosso exemplo de cachorro marrom, poderíamos fazer com que
cachorro marrom implementasse uma interface de cachorro e implementasse
uma interface de animal marrom. E então o cachorro marrom
teria dois contratos para
cumprir a interface do cão e
a interface do animal marrom. Com base nessas informações, classes
abstratas são úteis quando temos hierarquias de
objetos simples As interfaces são úteis
quando temos um objeto cujos contratos devem misturar e combinar métodos de
várias hierarquias Digamos que temos um cachorro marrom que
herda de uma classe de cães,
e a classe de cães herda
de uma classe de mamíferos Essa é uma hierarquia linear e faz sentido implementar nossos contratos de métodos
como classes abstratas Por outro lado,
digamos que temos um cachorro marrom e gostaríamos que ele preenchesse o modelo
de objeto de um animal colorido. E também gostaríamos que ele preenchesse o modelo de um
animal com pernas. Animais coloridos e animais com pernas são duas hierarquias de
objetos separadas Obviamente, existem
muitos animais que deveriam cumprir os dois contratos, mas também existem animais que cumprem
apenas um ou outro. Como você pode ver,
escolher interfaces ou classes
abstratas se
resume a como você decide projetar
sua hierarquia de classes Agora vamos ver como realmente
usamos interfaces na prática. Primeiro, definimos uma interface
chamada animal with legs e declaramos um
método que deve ser implementado chamado get non legs Também definiremos uma interface
chamada animal colorido que declara um
método que deve ser implementado chamado get color Agora vamos criar uma classe de cães
marrons. A primeira coisa que quero que você
note é que estamos usando a palavra-chave implements
aqui em vez de extends A próxima coisa que quero que você
veja é que aqui
especificamos várias
interfaces que devem ser implementadas
pelo brown dog. Se você tentar fazer isso
com a palavra-chave extends, Java gerará um erro. Esse é um recurso
exclusivo das interfaces, sendo capaz de implementar
várias coisas. Porém, além da
definição da classe, o resto da classe parece muito semelhante ao
que vimos. Como precisamos
implementar todos os métodos declarados nas interfaces
que estamos implementando, definimos tanto get color
quanto get numb legs Também adicionamos a
anotação de substituição para deixar explícito que essas implementações se
destinam a substituir É basicamente
isso. Neste vídeo, falamos sobre interfaces, que são um novo tipo
de classe que declara
um contrato que deve ser cumprido pelas classes
que as implementam. As interfaces permitem que você crie vários
padrões de herança que você não
pode fazer com classes
abstratas regulares Aqui está o link para o
código do repositório usado neste vídeo. Visite o link para bifurcar o repositório e
mexa Te vejo no próximo vídeo.
12. Enums: Olá amigos. Neste vídeo falaremos sobre enums Vamos começar a
ilustração de hoje
definindo uma classe chamada dog one, que tem um método get type
que apenas retorna brown dog. Digamos que também temos
uma classe chamada dog two, que também tem um método
get type, mas essa retorna white dog. Finalmente, temos o cachorro três. O cão três recebe o tipo
retorna cão amarelo. Sim, isso é um amarelo
com um H em vez de um W. Agora vamos juntar
tudo. Temos nossas três
definições de cães à esquerda e , à direita,
instanciamos três cães, uma instância para cada classe Digamos que queremos fazer
algumas verificações simples. Só queremos ligar,
digitar cada um desses cães. Em seguida, verifique a saída. Se a saída corresponder a
algum valor esperado. Vamos imprimir algo
para nosso primeiro cachorro. Queremos verificar se o tipo
de cachorro é marrom. Para o segundo cachorro,
vamos verificar se
é um cachorro branco. Finalmente, para o terceiro cachorro, queremos verificar se
é um cachorro amarelo. Bem, como
acidentalmente escrevemos errado “cachorro
amarelo ” em nossa definição de tipo “cachorro
três”, essa condição
será falsa e
não imprimimos que o
cachorro Isso não é um grande problema em
um programa simples como esse, mas posso oferecer uma situação de
maior risco. Imagine que seu
site busque tráfego de vários países e você queira alterar
o idioma
do site com base no
país de origem do usuário. Digamos que, para
alguém no Japão, você queira definir
o idioma
do site como japonês. Semelhante a essa lógica, você teria
várias declarações if. Escolher o idioma
do site com base no país do usuário. Agora, digamos que escrevemos incorretamente Japão em algum lugar do nosso código Agora, esse usuário
japonês não vai aprender o idioma certo e você acabou perder vendas em potencial. Seria ótimo se
pudéssemos nosso código
contra esses erros de digitação, e temos uma ferramenta que
faz exatamente isso Vamos criar uma
classe enum chamada dog type. Normalmente, quando criamos uma classe, escrevemos o nome da classe pública. Mas aqui, observe que estamos
dizendo enum público, tipo de
cachorro dentro desse enum Em seguida, definimos três valores amarelo, marrom e branco. Observe que esses três valores
não estão entre aspas, não
são cadeias de caracteres. Talvez ainda não esteja
claro como isso ajuda. Vamos dar uma olhada em
como os usamos. Vamos definir um novo
método para cada uma de nossas classes de cães
chamado get enum type Podemos então ver que, para o cão um, esse método retorna o
tipo marrom e retornamos o tipo branco
e o tipo doc amarelo. Para os outros dois
cães, isso pode parecer basicamente
o que tínhamos antes, mas há uma distinção muito
importante aqui. O Enum age de forma semelhante a uma
variável ou campo em Java, Java pois o Java
executa uma pesquisa quando
você o referenciar Quando eu digo doc type brown, Java realmente pesquisará a
classe enum
do tipo dog e verá se há um valor dentro dela chamado Se não houver esse valor, o Java falhará na compilação Esse é um dos principais
benefícios dos enums. Os enums permitem que o Java
realize uma verificação em tempo de compilação verificar se todos os
valores de referência realmente existem Isso reduz a chance de você digitar incorretamente seus valores de
referência Enums também significam que há
uma fonte verdadeira para valores
constantes,
em vez de antes, quando escrevíamos manualmente cada
string para comparar valores Agora podemos fazer
algo assim, onde temos uma garantia
mais forte de que o valor constante ao qual estamos nos
referindo realmente existe. Se acidentalmente escrevêssemos incorretamente o
doctype yellow aqui, onde colocamos Y E L L
O H. Java
falharia na compilação porque
entraria falharia na compilação porque . Perceba que não
existe documento do tipo Y L L O H.
Isso é tudo neste vídeo. Falamos sobre enums, que nos permitem definir valores
constantes para
nossos aplicativos Esses valores constantes
são úteis porque, se alguma vez
tivermos uma
referência incorreta a um enum, o
Java gerará um erro de
compilação e saberemos exatamente
onde Os enums também fornecem uma fonte
de verdade para nossas constantes. Você define suas
constantes em um lugar e sempre se refere a
essas constantes em outros lugares do
seu programa, em vez de reescrever o valor
repetidamente Aqui está o link para o código
Repl neste vídeo. Te vejo na próxima.
13. Switch: Olá amigos. Neste vídeo falaremos sobre o switch. Vamos começar nossa
ilustração com definições
semelhantes
do último vídeo. Teremos um tipo de cachorro com três tipos de cores e
um cachorro marrom cujo método get type
retorna o tipo de cachorro marrom. Agora, em nosso método principal, vamos instanciar um cachorro marrom Diremos que se o tipo
de cachorro marrom for estampa branca,
o cachorro é branco. Se o
tipo do cachorro marrom for amarelo, imprima que os cães são amarelos. Se o tipo de cachorro for marrom, imprima que o cachorro é marrom. Caso contrário, imprima que a cor do
cachorro é desconhecida. Agora, não há nada realmente
errado com esse código. Funciona perfeitamente bem. Mas observe que aqui temos o mesmo valor em
todas as cláusulas if E não só isso, temos a mesma estrutura lógica
em cada cláusula if, comparando o mesmo valor
com diferentes tipos de enumeração Novamente, não há nada de errado com isso do
ponto de vista funcional, mas parece desajeitado Acontece que o Java tem
uma solução para isso. Aqui está uma forma alternativa de
escrever a mesma coisa. Antes de começar a falar
sobre esse código, quero que você mesmo dê
uma olhada. Você consegue adivinhar o que cada
nova palavra-chave está fazendo? Pause o vídeo e
quando estiver pronto. Vamos ver o quão perto você estava. Em primeiro lugar, essa
cláusula de troca na parte superior está basicamente dizendo
que queremos comparar esse valor
repetidamente. Vamos comparar
o valor dentro dos parênteses do switch com
os valores que seguem
essas palavras-chave de
maiúsculas valores que seguem
essas palavras-chave de
maiúsculas Esta cláusula do primeiro caso é
praticamente equivalente a se o tipo de cachorro
marrom ponto get for
igual ao tipo de cachorro branco O segundo é equivalente a if brown doggettype for igual
ao dog type yellow Você provavelmente pode adivinhar o que significa
a cláusula do último caso. Observe que, nessas
cláusulas de caso, não dizemos tipo de
cachorro branco e tipo de
cachorro amarelo Nós apenas dizemos branco e amarelo. O motivo é que,
nos blocos de comutação, Java deduz o tipo de enumeração, o valor entre parênteses de
opção,
e espera que você simplesmente escreva os valores de enumeração e espera que você simplesmente escreva sem
o nome da classe de enumeração Esse é um ponto relativamente pequeno, mas lembre-se disso se
você encontrar algum erro. Finalmente, esse caso padrão é aproximadamente equivalente a
else, mas não exatamente. Na verdade, significa sempre executar esse caso se o programa
atingir essa linha. No entanto, só
chegamos a esse caso
no caso Ls por causa
dessas declarações de quebra. Mas o que eles são? Acontece que essas
instruções de interrupção interrompem avaliação
adicional
dentro do bloco switch se o caminho
do código chegar até elas. Por exemplo,
digamos que não tivemos a quebra da
cláusula marrom no caso Brown Se fosse esse o caso, todo esse código seria executado. Imprimiríamos
que o cachorro é marrom. E então, como
não há mais linha de freio, Java continuaria executando
o código no próximo caso O próximo caso aqui
é o caso padrão. Também imprimiremos a cor de cachorro
desconhecida. Como você pode ver, se nosso bloco de switch tivesse
muito mais caixas,
seria uma grande perda de
tempo se continuássemos executando o código mesmo depois de
já encontrarmos o tipo
de cachorro marrom. Em geral, quando você
espera que apenas uma caixa
seja compatível, é
recomendável definir
uma linha de freio em É isso para este vídeo. Nesta lição,
falamos sobre switch, que basicamente é apenas
uma maneira mais concisa de escrever lógica repetitiva,
se else. Aqui está o link para o código
Repl neste vídeo. Te vejo na próxima.
14. Campo Minado Passo a passo 2: Bem-vindos, amigos. Neste vídeo, vamos
percorrer a segunda parte
desse projeto usando o que
aprendemos nas últimas lições, especificamente enums e switch Desta vez, vamos
realmente
dar uma olhada na classe principal. Há muita coisa
acontecendo nesse arquivo. Antes de começarmos, reserve
um momento para lê-lo. Tudo bem se houver
partes que você não entende. Muitos dos nomes das variáveis
são bastante descritivos e devem, pelo menos,
dar uma dica
decente do que Agora vamos passar por
isso juntos. Primeiro, criamos uma placa, imprimimos a placa e depois começamos um loop
infinito aqui. Essa linha de entrada do scanner
basicamente diz ao console que veja o que o usuário inseriu
no turno atual. Lembre-se de que, em nossa demonstração,
fizemos coisas como sinalizar coluna de linha e
tocar coluna de linha. Tudo o que você inserir no
console será salvo nesta string inserida pelo usuário aqui, divisão da entrada
do usuário
significa apenas que vamos
separar uma string
com base no espaço em branco. Por exemplo, quando
tocamos um espaço B
, devemos terminar com uma matriz que contém
três elementos. O primeiro elemento será tap, o segundo elemento será A
e o terceiro
elemento deverá ser B. É por isso
que, e o terceiro
elemento deverá ser B. se o comprimento
da matriz não for três, rejeitaremos o comando
e reiniciaremos o loop. Talvez você não esteja familiarizado
com essa linha contínua. Tudo o que ele faz é dizer ao Java que
pule o resto do loop
e comece do topo Novamente, vamos voltar
ao topo desse loop y, verificar a próxima entrada do usuário. Aqui temos uma linha
igual a menos um, seguida por um loop vazio coluna é igual a menos um, também seguida por um loop vazio Voltaremos a
isso em um vídeo posterior. Não é muito
importante por enquanto. Saiba que a linha e a
coluna
serão números inteiros que representam os índices
do quadro no qual o usuário gostaria de
realizar uma ação Finalmente, chegamos a uma
parte do código na qual
estamos interessados. Aqui, criamos um lingote
chamado célula segura. Temos um
bloco de interruptores vazio que o segue. Abaixo dizemos que se a célula segura é
falsa, então o jogo acaba. Isso implica que
esse bloco de comutação deve alterar o
valor da célula segura. Caso contrário, sua célula
segura sempre será verdadeira. E seria redundante
ter esse caso F aqui. Pense na última
caminhada que fizemos. Você consegue pensar no método que implementamos que retorna um valor em ouro indicando se uma torneira era
segura ou não A resposta é que você
implementou o método tap. Lembre-se de que tínhamos
esse método Tap que
registra que a célula foi tocada para células numéricas
e as células vazias
retornarão verdadeiras para
células mentais, retornamos falsas E se você explorasse
um pouco mais um código, teria visto que no Board Java também temos um
método tap. E o que fazemos? Primeiro, tocamos na
célula localizada na coluna da linha de
índice e salvamos o resultado desse toque
nesse resultado de toque em ouro Se fosse uma torneira segura e não houvesse
minas ao redor dela, então tocamos em todas as células
vizinhas
ao redor dela e retornamos ao redor dela e retornamos Caso contrário, se colarmos
uma mina, retornaremos falso. implica que, dentro
desse bloco de comutação, devemos chamar a coluna
tap row, salvar o resultado dessa
chamada em uma célula segura. Mas lembre-se de que um bloco de comutação é usado quando temos
vários casos para verificar quais casos
devemos verificar dentro
dessa caixa de troca. Mais uma vez, pause o
vídeo e pense que discutimos que estava acontecendo no
início do passeio Vou revelar a resposta em 321. Bem, a única vez
que obtemos um valor para a célula
segura é quando
tocamos em uma célula. Mas essas não são as únicas
ações que um usuário pode realizar. Lembre-se do
vídeo de introdução do projeto que um usuário também pode sinalizar e desmarcar uma célula se
você esquecer o que Basicamente, a bandeira
marcará uma célula como uma mente em potencial,
mas não tocará na célula. removerá uma bandeira
da Também removerá uma bandeira
da célula sem
tocar na célula Como o comando do usuário
vai assumir
a coluna de linha de ação do formulário, vamos colocar o comando zero dentro desses
parênteses Nosso primeiro caso
será uma torneira. Se o usuário inserir um toque como comando,
diremos reatribuiremos
o valor de uma célula segura como resultado de um toque no quadro na
coluna da linha de
posição Não se esqueça de que, depois realizar qualquer ação que
desejamos realizar
nesse caso, precisamos deixar uma
declaração de interrupção antes do próximo caso. Se o comando do usuário fosse um sinalizador, qual método deveria ser recuperado? Bem, aqui está uma boa chance de usar nossas habilidades de leitura de código. Vamos ver quais outros métodos
estão na classe board. Temos um
método resolvido aqui, mas isso
realmente não parece provável. Ei, aqui temos uma bandeira
e um método não alimentado. Eles parecem se adequar ao nosso caso de uso, vamos usá-los novamente
em nossa classe principal. No caso da bandeira,
vamos chamar a coluna da bandeira. Como esse método retorna, não pretendemos realmente usar o valor de retorno desse método para fazer qualquer outra coisa, apenas
quebramos. Finalmente, teremos
nosso último caso, que é o caso da bandeira aqui. Vamos fazer a coluna da bandeira, depois vamos quebrar também. No entanto, temos um pequeno
problema aqui. É totalmente possível
que um usuário insira alguma string aleatória
como comando de entrada, ou que o usuário
tenha
escrito acidentalmente incorretamente tap flag ou unflag Mas queremos tornar
esse código mais robusto e é aí que
os enums entram em Vamos predefinir alguns valores
possíveis que queremos
aceitar do usuário Aqui em cima na ação, hum, vamos
definir unflagg, tap Realmente não importa em que
ordem você os escreve. Agora, aqui, vamos converter esses valores de maiúsculas e minúsculas em
strings, valores enumerados Isso protegerá contra
possíveis erros de digitação. Vamos
transformá-lo em uma torneira. Vamos transformar isso em uma bandeira, vamos transformar isso em uma bandeira da ONU. Mas agora temos um pequeno problema. Lembre-se de que o Java inferirá
o tipo do valor
nesses parênteses e verificará se
esse tipo corresponde ao tipo desses valores
de maiúsculas e minúsculas Mas esse não é o caso aqui. O tipo de comando
zero é uma string. O tipo desses
valores de caso é uma enumeração de ação. Como convertemos uma string
em uma enumeração de ação? Bem, esta é uma oportunidade
fantástica de
aprimorar nossas habilidades de pesquisa no Google. Vamos continuar e pesquisar no Google
Java como converter uma string, uma string, em
uma enumeração. Vamos clicar
no primeiro resultado aqui. Nós rolamos para baixo. verdade, não precisamos ler
a maior parte disso, mas podemos ver
aqui no bloco de código eles estão informando
que têm um enum chamado status Pisa Hum, e tem um
valor dentro disso. Enumeração do status da peça. Pronto? Vamos rolar
um pouco mais para baixo. Vemos que temos esse
exemplo, Pisa status enum. Exceto que desta vez derivamos
o valor do enum, não dizendo patatenum, pronto,
mas parte do status, valor enum da string, Essa é uma boa
dica para nos dizer
que o método value de uma classe enum converterá
uma string em um enum Vamos usar isso em
vez do comando zero, vamos fazer o valor da ação
do comando zero. Agora, isso é praticamente tudo o
que tivemos que fazer para essa caminhada. Infelizmente, mais uma vez, não
poderemos
ver o resultado do que fizemos até
terminarmos todo o projeto. Mas espero que você fique
por aqui para ver o resultado final. Isso é tudo para este vídeo. Obrigado por assistir e nos
vemos na próxima.
15. Exceções: Olá amigos. Neste vídeo falaremos
sobre exceções. Vamos revisitar o exemplo que
tivemos no vídeo anterior. Lembre-se de que nosso cão tipo
enum tinha três tipos:
branco, marrom e amarelo Se o tipo de cachorro correspondesse a
qualquer um desses três casos, imprimiríamos uma declaração e seguida, sairíamos
do bloco de troca A única vez que encontraremos
esse caso padrão é se tipo de cachorro
marrom não tiver nenhuma
dessas três cores, mas só tivermos
esses três tipos definidos. Quando
encontraríamos esse caso? Bem, pode ser se o tipo for nulo ou talvez
no futuro acabemos
adicionando um tipo extra de cachorro Mas esqueça de atualizar
esse bloco de comutação. Mas, de um modo geral, não
esperamos atingir esse
caso padrão na maioria dos casos de uso. Se atingirmos esse
caso padrão com esse código, na verdade
teremos
uma falha silenciosa. Teremos uma linha extra sendo impressa, cor de cachorro desconhecida. Mas o programa funciona muito bem. Ele não falha na compilação e não há erro
quando o executamos Não sabemos se a cor
desconhecida do cachorro sendo impressa
era esperada ou não. Em vez disso, o que devemos
fazer é lançar uma exceção. Aqui está um exemplo de um
dos tipos mais comuns de exceções, exceção estadual
ilegal Observe isso no texto aqui. Dizemos throw, o que faz com que o
Java lance um erro. Em seguida, fornecemos uma nova
instância da exceção com new e passamos uma
mensagem de erro para a exceção. Agora, se o Java atingir
essa linha de código, um erro será
gerado quando você executar o programa e o
programa será interrompido. Isso é realmente uma coisa boa. Digamos que você adicionou um tipo
extra de cachorro chamado Blue, mas se esqueceu de
adicionar um estojo para ele Você quer que o código pare
e diga que há um tipo desconhecido em vez de continuar sendo executado como
se nada tivesse acontecido. É difícil ver
isso com esse pequeno programa. Mas imagine que você tenha um aplicativo muito
mais importante. Por exemplo, digamos que
haja um aplicativo que informa quanto
dinheiro você tem no banco. É muito melhor que
o banco diga que
houve um erro ao carregar
sua conta do que falhar
silenciosamente dizendo
que você tem $50.000
negativos em sua conta,
tanto para o desenvolvedor
quanto para o usuário do aplicativo O erro explícito é muito mais
informativo do que uma saída estranha
arbitrária. O benefício adicional para
o desenvolvedor é que o erro
personalizado realmente
dirá onde algo
inesperado aconteceu. Isso também torna a depuração
muito mais fácil. É isso para este vídeo. Falamos sobre exceções que interrompem
deliberadamente os programas
com a mensagem de erro personalizada Embora, à primeira vista, isso possa parecer uma
coisa terrível para adicionar ao seu programa Mas, na verdade, eles ajudam a garantir a estabilidade do
programa fornecendo verificações de integridade e
fornecendo dicas
ao desenvolvedor
no caso de um bug Aqui está o link para o
código de repelência usado neste vídeo. Te vejo na próxima.
16. HashMap: Bem-vindos amigos. Neste vídeo falaremos
sobre o mapa de hash O exemplo de hoje é bem curto e pode caber em um arquivo. A primeira coisa
que quero que você note é essa importação na
parte superior do arquivo. O mapa de hash é uma estrutura de
dados incluída no pacote
Java Util,
que é um pacote incorporado A seguir, vamos dar uma olhada em
como declaramos um Hashmap. Como de costume, primeiro declaramos o tipo da variável
que é um Hashmap Em seguida, usamos esses
colchetes angulares para especificar os tipos de chaves e
valores dentro desse mapa O número inteiro entre colchetes
angulares especifica o tipo das teclas A string entre colchetes especifica o tipo
dos valores Uma chave é basicamente
algo que
vamos usar para pesquisar valores. Por exemplo, pense na lista de
contexto em seu telefone. Quando quiser pesquisar o número de telefone do
seu amigo, primeiro
procure o nome
dele. Quando você clica no nome, seu telefone exibe o número de telefone do
seu amigo. O nome do seu amigo é uma chave mapeada para um número de telefone
que é um valor. Nesse caso, vamos
mapear números inteiros para strings Observe também que usamos inteiro I
maiúsculo
aqui em vez de t
minúsculo quando
declaramos tipos inteiros que
estão contidos em outros
objetos como uma chave em um mapa,
usamos um inteiro I maiúsculo, mas, caso contrário, inteiro maiúsculo e T
minúsculo são praticamente intercambiáveis e T
minúsculo A seguir, vamos ver como
instanciamos um mapa de hash. Observe que ainda
incluímos os colchetes angulares, mas não colocamos
nada neles. Isso porque essa
sintaxe diz ao Java que simplesmente deduza os tipos
de chaves e valores Do lado esquerdo
dessa tarefa, Java saberá
criar um mapa de hash com chaves inteiras
e Na próxima linha, o mapa colocado um amarelo diz que agora
estamos mapeando um para amarelo dentro do mapa. O ponto colocado em marrom significa que
mapeamos dois para marrom. Quando imprimimos um ponto no mapa, imprimimos em amarelo. Quando imprimimos o ponto do mapa, obtemos dois pontos, imprimimos em marrom. Parece muito simples
e geralmente é. Uma coisa que eu quero destacar
aqui é que essas compras e saídas acontecem
em tempo constante. Na verdade, não falamos
sobre o que essa notação O de um significa
porque não é realmente um
foco nesta classe Você realmente não precisa saber
em detalhes o que está acontecendo, mas vou lhe dar
uma breve visão geral. O
mapa de hash e hash é, na verdade um mecanismo de
programação que permite ao computador armazenar
objetos de uma forma que seja muito fácil e rápido
recuperá-los posteriormente Ainda leva tempo para recuperar
e armazenar esses objetos, mas o tempo é praticamente
insignificante na maioria dos Os mapas são ótimos
para armazenar dados. Tudo bem, então é
isso para este vídeo. Falamos sobre o mapa de hash, que é uma estrutura de dados que armazena e mapeia chaves para valores Ele faz tudo isso
em tempo constante, o que
significa que a latência necessária
para gravar e ler no mapa não aumenta muito à medida que aumentamos o
número de itens no mapa Aqui está o link para o
código de repelência usado neste vídeo. Te vejo na próxima.
17. Adendo de mapa: Bem-vindos amigos. Neste
vídeo, abordaremos recurso adicional do
Java relacionado aos mapas de hash Aqui está o exemplo que tivemos
no vídeo anterior com um
pouco mais de código nele. Primeiro, vamos importar
Java até o mapa de pontos. A seguir, vamos dar uma
olhada nessa linha. Abaixo, declaramos
uma variável chamada x e damos a ela um tipo de
mapa, inteiro, inteiro Nós o instanciamos
usando o mapa 1234. Algumas coisas a serem observadas aqui. Primeiro, um mapa não é o
mesmo que um mapa de hash. Um mapa é na verdade uma interface, e um mapa de hash é uma
implementação concreta dessa interface Segundo, um mapa criado com
map of será imutável, que
significa que você não pode modificar suas chaves ou valores
depois de Esse mapa de sintaxe parece engraçado, mas é basicamente equivalente
a mapear a chave um para o valor dois e a chave
três para o valor quatro Se conseguirmos
um, teremos dois. Como um mapeia para dois, se x pontos obtiverem dois, obteremos um valor nulo porque
dois é um valor, não uma chave Como a chave dois não
existe, obtemos um resultado nulo. Finalmente, o registro três nos
dará quatro, já que chaves e valores se
alternam na chamada de mapa de criação e nós a
especificamos três após o valor dois É isso para este vídeo. Eu só queria apresentar
uma maneira rápida de instanciar um mapa se você não quiser
primeiro criar o mapa e
depois preenchê-lo com chaves e
valores, um por um,
para recapitular rapidamente Os mapas criados dessa
forma são imutáveis. Quando fazemos isso, alternamos chaves e valores
no mapa de chamada. Aqui está o link para o código de
repelência neste vídeo. Te vejo na próxima.
18. HashSet: Bem-vindos, amigos. Neste vídeo, falaremos
sobre o conjunto de hash O exemplo de hoje é bem parecido com o do último vídeo. Ele cabe em um arquivo e até a sintaxe é bem
semelhante. Vamos entrar nisso. A primeira coisa que
você deve observar é que, assim como o mapa de hash, conjuntos de
hash devem ser importados
explicitamente Os conjuntos de hash também estão
no pacote Java Util. A seguir, vamos dar uma olhada na declaração da
variável. Declaramos um conjunto de hash
e, dentro desses colchetes
angulares,
declaramos o tipo dos elementos que estarão Usamos números inteiros com I maiúsculo pois estamos agrupando os
números inteiros em um contêiner, assim como listas ou mapas de hash Ao instanciar
os conjuntos de hash, não
precisamos
especificar o tipo dos elementos no lado direito
da atribuição Podemos simplesmente colocar colchetes
angulares vazios e o Java inferirá o
tipo dos elementos a partir da declaração
da variável no lado esquerdo
da O método de anúncio nos permite
armazenar itens no conjunto. Observe que o Java
não permitirá que você coloque um objeto
diferente de um número inteiro no conjunto Você não poderá colocar
strings ou valores de barras de ouro. Você receberia um
erro de tempo de compilação se tentasse isso. Aqui, se tentarmos adicionar 35 depois de já termos
feito isso anteriormente, nada realmente mudará. Esse é um dos principais
recursos dos conjuntos de hash. Os conjuntos de hash
armazenarão apenas itens exclusivos. Se você tentar adicionar
o mesmo item duas vezes, Java não errará, mas também não fará
nada diferente. Também temos um método de tamanho, e você provavelmente pode
adivinhar o que isso faz. Ele apenas retorna o número
de itens no conjunto. Nesse caso, são dois. Como temos apenas
35,91 no conjunto,
o método contido
retorna verdadeiro ou falso dependendo se
o
item solicitado já está no conjunto É verdadeiro para 35 e
é falso para 36. Você também pode remover
itens do conjunto. Se você chamar itens
que removem 35
, 35 não estará
mais no conjunto. Podemos confirmar ligando para
itens que contêm 35, que retornarão falsos. Agora, uma última
lição importante para você. Assim como os mapas de hash, os conjuntos de hash também usam o mecanismo de hash Você não precisa saber os
detalhes, mas apenas saber que essas chamadas contêm
adição e remoção, tudo acontece em tempo constante. O que significa que o tempo necessário
para executar esses métodos
não aumenta significativamente à medida
que o tamanho do conjunto aumenta. Isso pode ser muito útil
quando você deseja usar uma estrutura de dados para pesquisas e armazenamento realmente
rápidos. Digamos, por exemplo,
que você queira verificar se um determinado anúncio
já foi reproduzido para um usuário Dessa forma, sempre podemos
exibir anúncios exclusivos. Bem, uma forma de
representar isso é que cada objeto de usuário tem um
conjunto de hash associado a ele ou ela Esse conjunto contém
os
objetos de anúncio que o usuário
já viu Esse é apenas um exemplo básico. E teremos outro caso de uso para conjuntos de hash no projeto, que você verá em breve Tudo bem, e isso é
tudo para este vídeo. Nesta lição,
falamos sobre conjuntos de hash que nos permitem armazenar
valor para pesquisas posteriores Eles também têm direitos de leitura em
tempo constante, o que os torna muito úteis
em diversos casos de uso, como o
exemplo de anúncio exclusivo sobre o qual falamos Aqui está o link do repositório para
o código neste vídeo. Te vejo na próxima.
19. Passo a passo 3: Bem-vindos amigos.
Neste vídeo, abordaremos uma das partes mais impactantes do projeto Usando o que aprendemos
nos últimos vídeos em Java. Role para baixo até esse método chamado reunir células vazias
vizinhas Vamos dar uma
olhada no que ele faz. Essa classe Q vinculada ao bloqueio Q pode não parecer familiar para
você, não se preocupe com isso. Não é muito relevante
para o curso. Tudo o que você realmente precisa saber
sobre isso aqui é que ele está nos ajudando realizar algo chamado BFS,
ou Breadth ou Breadth Isso é respiração, como em B, R, E, A, D, T, H. Não falamos
sobre isso no discurso E não é realmente
necessário que você saiba como isso
funciona especificamente. Mas fique à vontade para
pesquisar no Google se estiver curioso, porque é
um conceito muito legal. Nesse método, nossa
pesquisa BFS está coletando todas as células vazias
adjacentes à
linha e coluna fornecidas Depois de coletar todas as células vazias
adjacentes, ele procura células
vazias
adjacentes às células vazias que já
coletamos E então continuamos procurando
células vazias adjacentes a essas
células vazias, e assim por diante. Como você deve ter adivinhado,
isso faz parte
do código que manipula um
toque em uma célula vazia Lembre-se de que, quando você
toca em uma célula vazia, normalmente uma grande parte
do tabuleiro é tocada para
nós Isso é feito por meio desse método, que informa ao programa
onde estão localizadas todas as células vazias adjacentes à célula em que você
tocou Antes de prosseguirmos,
quero reconhecer que alguns de vocês podem estar se sentindo um pouco frustrados com
essas orientações Talvez você pense: ei, por que não falamos sobre o BFS
nos vídeos explicativos Por que estamos sendo apresentados a novas estruturas de dados e
algoritmos neste projeto? Bem, há algumas
razões para isso. A principal delas é que
uma grande parte de ser programador é ser
capaz de ler
um código desconhecido, entendê-lo pelo menos
parcialmente e depois modificá-lo Não é verdade que há uma quantidade finita de
Java que você pode aprender E somente depois
de aprender, você estará pronto para lidar com
todo o código do mundo. A verdade é que existem
muitas pessoas inteligentes por aí. E as pessoas usam todo tipo de
algoritmos e códigos difíceis de entender. Não há uma quantidade mágica de Java que você precise conhecer antes de estar pronto
para enfrentar o mundo. Aprender a trabalhar
com códigos com os quais você não está 100% familiarizado é
uma realidade cotidiana. Se você chegou
até aqui no curso, fico feliz que ainda esteja aqui e
aprendendo a aprender comigo. Tudo bem, agora
vamos finalmente examinar mais
de perto alguns
componentes principais desse método. Veja essa variável chamada, especialmente a linha
aqui que diz divisão de pólos. O que isso está fazendo
é remover
uma string da estrutura de
dados,
separar a string em
componentes usando o delímetro
e, em seguida, salvar o resultado
dessa divisão em Por exemplo, se
houvesse um item
no Q que fosse uma string a B
, o resultado da
divisão por o seria
uma matriz de dois elementos
cujo primeiro elemento seria uma matriz de dois elementos
cujo primeiro elemento a e cujo segundo
elemento seria B. Aqui você pode ver
que, em nosso caso, A é na um índice de linha
e B é na verdade
um índice de coluna Usamos esses índices para
selecionar uma célula em nosso quadro
e, em seguida, temos que fazer isso Na verdade, é muito difícil entender o que
precisamos fazer aqui. Se você nunca viu o BFS, não desanime se se sentir
perplexo Mas vou te dizer o que está
acontecendo aqui. Nesse loop que segue
o to do, temos essa linha A mais j. Como você provavelmente pode imaginar,
Ad adicionará a string,
nós a daremos a Q. Uma coisa que você talvez não
perceba imediatamente é que podemos adicionar
infinitamente itens a Q. E então nunca sairemos desse loop que verifica
se Q Basicamente, a ideia é que
queremos realizar apenas
esse loop aninhado aqui, no máximo uma vez, para
cada célula da placa Mas agora, se você
já viu a linha A na coluna B, ainda
pode adicionar
acidentalmente um B a Q e percorrer esse loop
aninhado novamente Portanto, precisamos acompanhar
todas as células que
já visitamos. Queremos armazenar
células que
já vimos na estrutura de
dados e, em seguida, executar esse loop aninhado
duplo
apenas na célula atual que ainda
não foi visitada Você consegue pensar em
uma estrutura de dados que aprendemos que permite inserção
e consultas rápidas Pense nisso e eu pausarei o vídeo e
responderei em 321,
a resposta é um conjunto de hash Podemos armazenar células que
já visitamos em um conjunto de hash Isso significa que se você encontrar uma célula que não esteja
no conjunto de hash, isso significa que você nunca
encontrou uma célula antes Dessa forma, podemos
garantir que só executaremos esse loop aninhado duplo em
cada célula no máximo uma vez Aqui está o que precisamos
fazer. Primeiro vamos
instanciar nosso
conjunto de hash chamado scene Então, aqui embaixo, vamos
primeiro verificar se
já vimos essa célula? Podemos usar o método sets
contains para T. Em seguida, envolvemos todo
esse loop duplo de
quatro aninhados dentro daqui e o transformamos em
negativo Se ainda não
vimos a célula especificada, adicionamos
essa célula ao conjunto de hash
da cena porque agora
visitamos essa célula Agora que
visitamos essa célula, realizamos nosso loop. Agora, garantimos que
esse loop nunca mais será executado. Por que isso? Bem, vamos ver, 1 segundo. Acho que
confundi esse recuo. Lá vamos nós. OK. Por que isso funciona? Digamos que encontremos uma célula que nunca foi vista
antes. Não vai
estar dentro da cena. Nós o adicionamos à cena
e, em seguida, executamos
esse loop duplo. Digamos que
acidentalmente adicionamos a célula que acabamos de ver
dentro de Q. Então, quando
passarmos pelo loop, novamente, vamos tirar a célula que
já vimos da fila E então vamos verificar se a cena não contém estalos. Bem, como
já adicionamos a célula que vimos na
cena definida aqui
, quando voltarmos a essa afirmação if
na próxima rodada, retornará falsa. Não poderemos
executar esse loop duplo aninhado nessa
célula em outra ocasião É isso para este vídeo. Agora cumprimos nossa tarefa. Estamos a apenas uma peça de poder
jogar nosso jogo. Nos vemos no próximo vídeo.
20. Passo a passo 4: Bem-vindos amigos. Neste vídeo , finalmente
concluiremos nosso jogo. Ao terminar
este vídeo, você poderá jogar
o jogo de forma interativa e compartilhar o link com seus amigos para que eles também possam jogar. Tudo bem, na primeira
parte desta apresentação, vamos
revisitar o Board Java Na parte superior desse arquivo, você deve ver que temos esse mapa de letra para num definido. Lembre-se de que, quando
você joga, nossos comandos assumem a forma. Ação, linha, coluna como a, B. Nossa linha e colunas
são inseridas como letras, mas precisamos converter
essas letras em índices. E nosso tabuleiro de caça-minas, nossos índices do tabuleiro,
começarão de cima para baixo,
da esquerda para a direita Em outras palavras, A
mapeia para o índice zero, mapeia para o índice um e mapeia para o índice
dois, e assim por diante. Aqui, só precisamos
definir esses mapeamentos.
Vamos fazer isso. Temos um mapeamento para zero, mapeamento para um. Rápido
, observe que
o fato de eu ter deixado uma nova linha entre cada par de valores, os
valores-chave, na verdade,
não são necessários. Você também pode simplesmente colocar tudo
isso em uma linha. Eu apenas o coloquei em
linhas diferentes para torná-lo mais bonito. Além disso, certifique-se de ter aspas duplas
nas teclas. Se você colocar aspas simples, isso é na verdade um tipo diferente de
Java chamado caractere. Em seguida,
vamos para Java principal, rolando para baixo até onde
temos linhas inteiras iguais É aqui que fazemos a
conversão de letra para número. Lembre-se do vídeo
anterior, onde
falamos sobre essa
matriz de comandos aqui, quando dividimos por espaço em branco, dividimos o comando do usuário
em três elementos. O comando é o
primeiro elemento, a letra da linha é
o segundo elemento e a letra da coluna
é o terceiro elemento. Lembre-se de que nossos índices
começam em zero. Isso significa que a letra
da linha estará no índice um. Nos comandos, vamos recuperar o mapeamento numérico
da linha fazendo a letra do
quadro para nu map get commands one here Este mapa da letra ao entorpecimento é o que acabamos de
definir aqui Ele pegará a
letra da linha que o usuário inseriu e , em seguida, buscará o índice
numérico ao
qual essa letra corresponde e que acabamos de definir
na outra classe Da mesma forma, vamos fazer
a mesma coisa com a letra do quadro de
colunas para os comandos
numb mapget Agora, na verdade, precisamos adicionar alguns aprimoramentos e
corrigir
um erro de digitação que cometi em vídeos
anteriores no Board Java onde implementamos reunir células vazias
vizinhas mudar de cena para célula de cena Na última linha
desse método na verdade, esperamos que
exista uma variável chamada células de cena. Foi minha culpa, peço desculpas. Vamos mudar a
cena para células de cena. Por fim, nas
classes de células que
implementamos em uma das
primeiras explicações sobre isso, certifique-se de
ter a caixa grampeada antes
da caixa sinalizada Isso ocorre porque, quando
você toca em uma célula, o estado da célula é definitivo. Você não pode sinalizá-lo ou destocá-lo. No entanto, se a bandeira vier primeiro
no método de duas cadeias, isso significa que se você sinalizar uma célula primeiro e
depois tocar nela, o tabuleiro ainda
renderizará o símbolo
do triângulo do tabuleiro em vez do estado tocado, pois verifica o touro da bandeira antes
do touro tocado Não se preocupe se isso for um pouco
confuso, é um bug complicado. O ponto principal desse projeto
era praticar a codificação, não encontrar bugs obscuros.
Não se preocupe com isso. Agora vamos tentar clicar em Executar e jogar nosso jogo. Agradável. Parece que o
jogo está funcionando. Estamos revelando
células numéricas, células
vazias reveladas em
todos os lugares apropriados. Também podemos tentar sinalizar
e obteremos uma bandeira
no lugar correto Tudo bem, então é
isso para este vídeo. Obrigado por ter chegado até aqui. Agora você pode jogar
e compartilhar com seus amigos. Te vejo no próximo vídeo.
21. Conclusão do módulo 2: Olá novamente. Bem-vindo
ao final deste curso. Parabéns. Agora você
criou uma taxa de minas em funcionamento por jogo que pode gerar
mais de 1 trilhão E você pode
usá-los para desafiar seus amigos e
mostrar em seu currículo. E, a propósito,
não estou exagerando, eu realmente quero dizer
mais de 1 Você pode verificar minha
matemática. Você também aprendeu várias maneiras
de criar código. Usando herança,
classes abstratas e interfaces. Você também aprendeu sobre estruturas de dados
úteis , como mapas e conjuntos de hash Pode ser difícil
acreditar em mim agora,
mas à medida que você
progride em sua carreira, você descobrirá que muitas tecnologias
avançadas são,
na verdade, construídas com
base em coisas básicas,
como herança e estruturas
básicas de dados, como as que você
aprendeu neste Você só vai ter que acreditar na
minha palavra por enquanto. Mas, eventualmente, espero que um dia você entenda o que quero dizer. Mais importante ainda, a programação é uma habilidade na qual todos estão
aprendendo continuamente. Não prometo
ter ensinado
tudo o que você precisa saber
sobre programação Java, mas espero ter lhe dado
uma visão mais clara
dos fundamentos para
que você esteja bem equipado para aprender
ainda mais por conta própria, seja por meio de
meus cursos futuros
ou por meio de outros cursos ou por meio de outros cursos Mais uma vez,
parabéns por terminar o curso e desejo tudo de
bom até a próxima vez.