Como explicar conceitos de programação orientada a objetos para uma criança de 6 anos

Você notou como as mesmas perguntas clichês sempre são feitas nas entrevistas de emprego - repetidamente?

Tenho certeza que você sabe o que quero dizer.

Por exemplo:

Onde você se vê daqui a cinco anos?

ou ainda pior:

O que você considera ser sua maior fraqueza?

Ugh ... me dê um tempo. Considero a resposta a esta pergunta uma grande fraqueza! Enfim, não é o meu ponto.

Por mais triviais que essas perguntas possam ser, são importantes porque fornecem pistas sobre você. Seu estado de espírito atual, sua atitude, sua perspectiva.

Ao responder, você deve ter cuidado, pois pode revelar algo de que se arrependerá mais tarde.

Hoje quero falar sobre um tipo de questão semelhante no mundo da programação:

Quais são os princípios básicos da Programação Orientada a Objetos?

Estive nos dois lados dessa questão. É um daqueles tópicos que são perguntados com tanta frequência que você não pode se permitir não saber.

Os desenvolvedores iniciantes e iniciantes geralmente precisam responder. Porque é uma maneira fácil para o entrevistador dizer três coisas:

  1. O candidato se preparou para esta entrevista?

    Pontos de bônus se você ouvir uma resposta imediatamente - mostra uma abordagem séria.

  2. O candidato já passou da fase do tutorial?

    Compreender os princípios da Programação Orientada a Objetos (OOP) mostra que você foi além de copiar e colar de tutoriais - você já vê as coisas de uma perspectiva superior.

  3. A compreensão do candidato é profunda ou superficial?

    O nível de competência nesta questão freqüentemente é igual ao nível de competência na maioria dos outros assuntos . Confie em mim.

Os quatro princípios da programação orientada a objetos são encapsulamento , abstração , herança ,e polimorfismo .

Essas palavras podem parecer assustadoras para um desenvolvedor júnior. E as explicações complexas e excessivamente longas na Wikipedia às vezes dobram a confusão.

É por isso que quero dar uma explicação simples, curta e clara para cada um desses conceitos. Pode soar como algo que você explica a uma criança, mas eu adoraria ouvir essas respostas quando conduzir uma entrevista.

Encapsulamento

Digamos que temos um programa. Possui alguns objetos logicamente diferentes que se comunicam entre si - de acordo com as regras definidas no programa.

O encapsulamento é obtido quando cada objeto mantém seu estado privado , dentro de uma classe. Outros objetos não têm acesso direto a este estado. Em vez disso, eles podem chamar apenas uma lista de funções públicas - métodos chamados.

Portanto, o objeto gerencia seu próprio estado por meio de métodos - e nenhuma outra classe pode tocá-lo, a menos que seja explicitamente permitido. Se você deseja se comunicar com o objeto, você deve usar os métodos fornecidos. Mas (por padrão), você não pode alterar o estado.

Digamos que estejamos construindo um pequeno jogo Sims. Existem pessoas e um gato. Eles se comunicam entre si. Queremos aplicar o encapsulamento, então encapsulamos toda a lógica "cat" em umCatclasse. Pode ser assim:

Aqui, o “estado” do gato é as variáveis privadasmood , hungrye energy. Também possui um método privado meow(). Pode chamá-lo quando quiser, as outras classes não podem dizer ao gato quando miar.

O que eles podem fazer é definido nos métodos públicossleep() , play()e feed(). Cada um deles modifica o estado interno de alguma forma e pode invocar meow(). Assim, é feita a vinculação entre o estado privado e os métodos públicos.

Isso é encapsulamento.

Abstração

A abstração pode ser considerada uma extensão natural do encapsulamento.

No projeto orientado a objetos, os programas costumam ser extremamente grandes. E objetos separados se comunicam muito uns com os outros. Portanto, manter uma grande base de código como essa por anos - com mudanças ao longo do caminho - é difícil.

Abstração é um conceito que visa amenizar esse problema.

Aplicar abstração significa que cada objeto deve apenas expor um mecanismo de alto nível para usá-lo.

Este mecanismo deve ocultar detalhes de implementação interna. Deve apenas revelar operações relevantes para os outros objetos.

Pense - uma máquina de café. Ele faz muitas coisas e faz ruídos estranhos sob o capô. Mas tudo que você precisa fazer é colocar o café e apertar um botão.

De preferência, esse mecanismo deve ser fácil de usar e raramente deve mudar com o tempo. Pense nisso como um pequeno conjunto de métodos públicos que qualquer outra classe pode chamar sem “saber” como funcionam.

Outro exemplo de abstração da vida real?

Pense em como você usa seu telefone:

Você interage com seu telefone usando apenas alguns botões. O que está acontecendo sob o capô? Você não precisa saber - os detalhes da implementação estão ocultos. Você só precisa conhecer um pequeno conjunto de ações.

Mudanças de implementação - por exemplo, uma atualização de software - raramente afetam a abstração que você usa.

Herança

OK, vimos como o encapsulamento e a abstração podem nos ajudar a desenvolver e manter uma grande base de código.

Mas você sabe qual é outro problema comum no design OOP?

Os objetos são geralmente muito semelhantes. Eles compartilham uma lógica comum. Mas eles não são inteiramente iguais. Ugh ...

Então, como reutilizamos a lógica comum e extraímos a lógica única em uma classe separada? Uma maneira de conseguir isso é a herança.

Significa que você cria uma classe (filha) derivando de outra classe (pai). Dessa forma, formamos uma hierarquia.

A classe filha reutiliza todos os campos e métodos da classe pai (parte comum) e pode implementar seus próprios (parte única).

Por exemplo:

Se nosso programa precisa gerenciar professores públicos e privados, mas também outros tipos de pessoas como alunos, podemos implementar essa hierarquia de classes.

Dessa forma, cada classe adiciona apenas o que é necessário para ela, enquanto reutiliza a lógica comum com as classes pai.

Polimorfismo

Estamos reduzidos à palavra mais complexa! Polimorfismo significa “muitas formas” em grego.

Portanto, já conhecemos o poder da herança e o usamos com alegria. Mas aí vem esse problema.

Digamos que temos uma classe pai e algumas classes filho que herdam dela. Às vezes, queremos usar uma coleção - por exemplo, uma lista - que contém uma mistura de todas essas classes. Ou temos um método implementado para a classe pai - mas gostaríamos de usá-lo para os filhos também.

Isso pode ser resolvido usando polimorfismo.

Simplificando, o polimorfismo oferece uma maneira de usar uma classe exatamente como seu pai, para que não haja confusão com a mistura de tipos.Mas cada classe filha mantém seus próprios métodos como estão.

Isso normalmente acontece definindo uma interface (pai) a ser reutilizada. Ele descreve um monte de métodos comuns. Em seguida, cada classe filha implementa sua própria versão desses métodos.

Sempre que uma coleção (como uma lista) ou um método espera uma instância do pai (onde os métodos comuns são descritos), a linguagem se encarrega de avaliar a implementação correta do método comum - independentemente de qual filho é passado.

Dê uma olhada em um esboço de implementação de figuras geométricas. Eles reutilizam uma interface comum para calcular a área de superfície e perímetro:

Tendo estes três figuras herdando o pai Figure Interfacepermite que você crie uma lista de misturada triangles, circlese rectangles. E trate-os como o mesmo tipo de objeto.

Então, se esta lista tentar calcular a superfície de um elemento, o método correto é encontrado e executado. Se o elemento é um triângulo,CalculateSurface()é chamado. Se for um círculo - então o de cirlceCalculateSurface()é chamado. E assim por diante.

Se você tem uma função que opera com uma figura usando seu parâmetro, não precisa defini-la três vezes - uma vez para um triângulo, um círculo e um retângulo.

Você pode defini-lo uma vez e aceitar um Figurecomo um argumento. Se você passar por um triângulo, círculo ou retângulo - contanto que eles implementem CalculateParamter(), seu tipo não importa.

Espero que tenha ajudado. Você pode usar diretamente essas mesmas explicações em entrevistas de emprego.

Se ainda encontrar algo difícil de entender, não hesite em perguntar nos comentários abaixo.

Qual é o próximo?

Estar preparado para responder a uma das perguntas mais clássicas da entrevista é ótimo - mas às vezes você nunca é chamado para uma entrevista.

A seguir, vou me concentrar no que os empregadores querem ver em um desenvolvedor júnior e como se destacar na multidão ao procurar emprego.

Fique ligado.