CodeGym /Blogue Java /Random-PT /Princípios OOP
John Squirrels
Nível 41
San Francisco

Princípios OOP

Publicado no grupo Random-PT
Oi! Na lição de hoje, falaremos sobre Princípios da programação orientada a objetos. Você já se perguntou por que Java é projetado exatamente como é? Quer dizer, você declara classes e cria objetos com base em classes, classes têm métodos, etc. Mas por que a linguagem é estruturada de forma que os programas consistem em classes e objetos, e não em outra coisa? Por que o conceito de "objeto" foi inventado e colocado em primeiro plano? Todas as linguagens são projetadas dessa maneira? Se não, que vantagens dá ao Java? Como você pode ver, são muitas perguntas :) Vamos tentar responder a cada uma delas na lição de hoje.

O que é programação orientada a objetos (OOP)?

Claro, Java não é feito de objetos e classes apenas por diversão. Eles não são um capricho dos criadores de Java, nem mesmo uma invenção deles. Existem muitas outras linguagens baseadas em objetos. A primeira dessas linguagens foi chamada de "Simula". Foi inventado na década de 1960 na Noruega. Além disso, os conceitos de "classe" e "método" apareceram no Simula. Pelos padrões de desenvolvimento de software, "Simula" parece uma linguagem antiga, mas qualquer um pode ver sua "semelhança familiar" com Java. Princípios da programação orientada a objetos - 1Você provavelmente pode facilmente ler o código escrito nesta linguagem e explicar em linhas gerais o que ele faz :)

Begin
	Class Rectangle (Width, Height); Real Width, Height;
			           
	 Begin
	    Real Area, Perimeter;  
	 
	    Procedure Update;      
	    Begin
	      Area := Width * Height;
              OutText("Rectangle is updating, Area = "); OutFix(Area,2,8); OutImage;
	      Perimeter := 2*(Width + Height);
              OutText("Rectangle is updating, Perimeter = "); OutFix(Perimeter,2,8); OutImage;
	    End of Update;
	 
	    Update;               
	    OutText("Rectangle created: "); OutFix(Width,2,6);
	    OutFix(Height,2,6); OutImage;
	 End of Rectangle;

       Rectangle Class ColouredRectangle (Color); Text Color;
			           
	Begin   	  
	    OutText("ColouredRectangle created, color = "); OutText(Color);
	    OutImage;
        End of ColouredRectangle;

 
      	 Ref(Rectangle) Cr;            
	 Cr :- New ColouredRectangle(10, 20, "Green"); 
End;
Este código de amostra de código foi retirado de "Simula - 50 anos de OOP" por Weekly-geekly. Como você pode ver, Java não é muito diferente de seu avô :) Isso se deve ao fato de que o surgimento do Simula marcou o nascimento de um novo conceito: a programação orientada a objetos. Wikipedia define OOP assim: "Programação Orientada a Objetos (OOP) é ​​um paradigma de programação baseado no conceito de "objetos", que podem conter dados, na forma de campos (frequentemente conhecidos como atributos), e código, na forma de procedimentos (muitas vezes conhecidos como métodos)." Na minha opinião, esta é uma definição muito boa. Não faz muito tempo que você começou a aprender Java, mas essa definição provavelmente não contém nenhuma palavra que você não conheça :) Hoje OOP é a metodologia de programação mais comum. Além de Java, Os princípios OOP são usados ​​em muitas linguagens populares das quais você já deve ter ouvido falar. Por exemplo, C++ (usado ativamente no desenvolvimento de jogos), Objective-C e Swift (usado para escrever programas para dispositivos Apple), Python (mais popular em aprendizado de máquina), PHP (uma das linguagens de desenvolvimento web mais populares), JavaScript ( é mais fácil dizer para que não serve) e muitos outros. Então, quais são os princípios da OOP afinal? Nós vamos te contar em detalhes. quais são os princípios de OOP afinal? Nós vamos te contar em detalhes. quais são os princípios de OOP afinal? Nós vamos te contar em detalhes.

Princípios OOP

Estes são os alicerces dos alicerces. As 4 principais características que juntas formam o paradigma de programação orientada a objetos. Compreendê-los é essencial para se tornar um programador de sucesso.

Princípio 1. Herança

Boas notícias: você já conhece alguns dos princípios da POO! :) Já encontramos herança algumas vezes nas aulas e conseguimos usá-la. A herança é um mecanismo que permite descrever uma nova classe com base em uma classe (pai) existente. Ao fazer isso, a nova classe empresta as propriedades e a funcionalidade da classe pai. Para que serve a herança e quais as vantagens que ela oferece? Acima de tudo, reutilização de código. Os campos e métodos declarados nas classes pai podem ser usados ​​nas classes descendentes. Se todos os tipos de carros tiverem 10 campos comuns e 5 métodos idênticos, basta movê-los para o Autoclasse pai. Você pode usá-los em classes descendentes sem problemas. Vantagens sólidas: quantitativas (menos código) e, como resultado, qualitativas (as aulas se tornam muito mais simples). Além disso, a herança é muito flexível — você pode adicionar a funcionalidade de gravação separada que está faltando nos descendentes (alguns campos ou comportamentos específicos de uma classe específica). Em geral, como na vida real, todos nós somos um pouco parecidos com nossos pais, mas também diferentes deles :)

Princípio 2. Abstração

Este é um princípio muito simples. Abstração significa identificar as características principais e mais significativas de algo, ao mesmo tempo em que descarta qualquer coisa menor e insignificante. Não há necessidade de reinventar a roda. Vamos relembrar um exemplo de uma velha lição sobre classes. Suponha que estamos criando um sistema de arquivamento para os funcionários da empresa. Para criar objetos "employee", escrevemos uma classe Employee . Quais características são importantes para descrevê-los no sistema de arquivamento da empresa? Nome, data de nascimento, SSN e ID do funcionário. Mas é improvável que precisemos da altura, cor dos olhos ou cor do cabelo do funcionário para esse tipo de registro. A empresa não precisa dessas informações sobre um funcionário. Assim, na classe Employee , declaramos as seguintes variáveis:, int age , int socialSecurityNumber e int employeeId . E abstraímos informações desnecessárias como a cor dos olhos. No entanto, se estivermos fazendo um sistema de arquivamento para uma agência de modelos, a situação muda drasticamente. A altura, a cor dos olhos e a cor do cabelo de uma modelo são características importantes, mas seu SSN é absolutamente irrelevante para nós. Assim, na classe Model , criamos as seguintes variáveis: String height , String hair , String eyes .

Princípio 3. Encapsulamento

Nós já nos deparamos com isso. Em Java, encapsulamento significa restringir a capacidade de ler e alterar dados. Como você pode ver, o termo é baseado na palavra "cápsula". Usaremos uma "cápsula" para ocultar alguns dados importantes que não queremos que outros alterem. Aqui está um exemplo simples da vida real. Você tem um nome e um sobrenome. Todos os seus amigos os conhecem. Mas eles não têm a capacidade de alterar seu nome ou sobrenome. Poderíamos dizer que o processo para fazer isso é "encapsulado" pelo sistema judicial: você só pode mudar seu sobrenome por meio do oficial de justiça, e só você pode fazer isso. Outros "usuários" têm acesso "somente leitura" ao seu nome e sobrenome :) Outro exemplo ilustrativo é o dinheiro guardado em casa. Deixá-lo à vista no meio do quarto não é uma boa ideia. Qualquer "usuário" (pessoa que for a sua casa) poderá alterar o valor do seu dinheiro, ou seja, poderá receber o seu dinheiro. Seria melhor encapsular em um cofre. Então, o acesso estaria disponível apenas para você e somente por meio de um código especial. Exemplos óbvios de encapsulamento com os quais você já trabalhou são modificadores de acesso (privado, público etc.), bem como setters e getters. Se você não encapsular oCampo de idade da classe Cat , então qualquer um pode escrever:

Cat.age = -1000;
O mecanismo de encapsulamento nos permite proteger o campo age com um método setter, onde podemos garantir que age não pode ser definido como um número negativo.

Princípio 4. Polimorfismo

Polimorfismo é a capacidade de trabalhar com vários tipos como se fossem o mesmo tipo. Além disso, o comportamento dos objetos será diferente dependendo do seu tipo. Isso soa complicado? Vamos entender isso agora. Tomemos o exemplo mais simples: animais. Crie uma classe Animal com um único método speak() e duas subclasses — Cat e Dog .

public class Animal {

   public void speak() {
      
       System.out.println("Hello!");
   }
}

public class Dog extends Animal {
  
   @Override
   public void speak() {
       System.out.println ("Woof-woof!");
   }
}

public class Cat extends Animal {

   @Override
   public void speak() {
       System.out.println("Meow!");
   }
}
Agora vamos tentar declarar uma variável de referência Animal e atribuir um objeto Dog a ela.

public class Main {

   public static void main(String[] args) {

       Animal dog = new Dog();
       dog.speak();
   }
}
Qual método você acha que será chamado? Animal.speak() ou Dog.speak() ? O método na classe Dog será chamado: Woof-woof! Criamos uma referência Animal , mas o objeto se comporta como um Dog . Se necessário, poderia se comportar como um gato, cavalo ou algum outro animal. O importante é atribuir uma subclasse específica à variável de referência Animal geral . Isso faz sentido, porque todos os cães são animais. Era isso que tínhamos em mente quando dissemos que "o comportamento dos objetos será diferente dependendo do seu tipo". Se criássemos um objeto Cat ...

public static void main(String[] args) {

   Animal cat = new Cat();
   cat.speak();
}
o método speak() exibiria "Meow!" Mas o que queremos dizer com 'capacidade de trabalhar com vários tipos como se fossem o mesmo tipo'? Isso também é bastante direto. Vamos imaginar que estamos criando uma barbearia para animais. Nossa barbearia deve ser capaz de aparar qualquer animal, então criamos um método trim() com um parâmetro Animal (o animal cortando o cabelo).

public class AnimalBarbershop {

   public void trim(Animal animal) {

       System.out.println("The haircut is done!"); 
   }
}
E agora podemos passar os objetos Cat e Dog para o método trim() !

public static void main(String[] args) {

   Cat cat = new Cat();
   Dog dog = new Dog();

   AnimalBarbershop barbershop = new AnimalBarbershop();

   barbershop.trim(cat);
   barbershop.trim(dog);
}
E aqui está o exemplo claro: a classe AnimalBarbershop trabalha com os tipos Cat e Dog como se fossem do mesmo tipo. Ao mesmo tempo, Gato e Cachorro têm comportamentos diferentes: cada um fala de maneira diferente.

Por que precisamos de POO?

Por que OOP surgiu como um novo conceito de programação? Os programadores tinham ferramentas funcionais, como linguagens procedurais. O que os levou a inventar algo fundamentalmente novo? Acima de tudo, a complexidade das tarefas que enfrentaram. Se há 60 anos a tarefa do programador era algo como "avaliar alguma expressão matemática", agora poderia ser algo como "implementar 7 finais diferentes para o jogo STALKER, dependendo das combinações das decisões do jogador feitas nos pontos A, B, C, DE , e F no jogo." Como você pode ver, as tarefas obviamente se tornaram mais complicadas nas últimas décadas. E, como resultado, os tipos de dados se tornaram mais complicados. Esta é outra razão pela qual OOP apareceu. Uma expressão matemática pode ser avaliada facilmente usando primitivas comuns. Nenhum objeto é necessário aqui. Mas a tarefa com os finais do jogo seria difícil de descrever sem o uso de classes personalizadas. Dito isso, é muito fácil descrevê-lo usando classes e objetos. Obviamente, precisaremos de várias classes: Game, Stalker, Ending, PlayerDecision, GameEvent e assim por diante. Em outras palavras, mesmo sem começar a resolver o problema, podemos facilmente "esboçar" uma solução em nossa cabeça. A crescente complexidade das tarefas forçou os programadores a dividi-las em partes. Mas isso não era tão fácil de fazer na programação procedural. E muitas vezes um programa era como uma árvore com muitas ramificações representando todos os caminhos de execução possíveis. Dependendo de certas condições, um ramo do programa ou outro foi executado. Para programas pequenos, isso era conveniente, mas era muito difícil dividir um grande problema em partes. Esta foi mais uma razão para o surgimento de OOP. Esse paradigma deu aos programadores a capacidade de dividir um programa em vários "módulos" (classes), cada um dos quais faz sua própria parte do trabalho. Ao interagir uns com os outros, todos os objetos realizam o trabalho do nosso programa. Além disso, podemos reutilizar nosso código em outro lugar do programa, o que também economiza muito tempo.
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION