JavaRush /Blogue Java /Random-PT /Princípios OOP

Princípios OOP

Publicado no grupo Random-PT
Olá! Você já se perguntou por que o Java foi projetado dessa maneira? No sentido de que você cria classes, com base nelas - objetos, classes possuem métodos, etc. Mas por que a estrutura da linguagem é tal 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 funcionam dessa maneira e, caso contrário, quais benefícios isso traz ao Java? Como você pode ver, há muitas perguntas :) Vamos tentar responder a cada uma delas na palestra de hoje.

Princípios OOP:

  1. Herança
  2. Abstração
  3. Encapsulamento
  4. Polimorfismo

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

É claro que Java é composto de objetos e classes por uma razão. Isso não é um capricho de seus criadores, nem mesmo uma invenção deles. Existem muitas outras linguagens baseadas em objetos. A primeira linguagem desse tipo foi chamada Simula e foi inventada na década de 1960 na Noruega. Entre outras coisas, Simula introduziu os conceitos de “ classe ” e “ método ”. Princípios de programação orientada a objetos - 2
Kristen Nygaard e Ole Johan Dahl - criadores de Simula
Parece que Simula é uma linguagem antiga para os padrões de programação, mas sua conexão de “família” com Java é visível a olho nu. Provavelmente, você pode ler facilmente o código escrito nele e explicar em termos 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;
O exemplo de código foi retirado do artigo Simula - 50 anos de OOP . Como você pode ver, Java e seu ancestral não são tão diferentes um do outro :) Isso se deve ao fato de que o surgimento do Simula marcou o nascimento de um novo conceito - a programação orientada a objetos. A Wikipedia fornece a seguinte definição de OOP: Programação orientada a objetos (OOP) é ​​uma metodologia de programação baseada na representação de um programa como uma coleção de objetos, cada um dos quais é uma instância de uma classe específica, e as classes formam uma hierarquia de herança. É, na minha opinião, muito bem sucedido. Você começou recentemente a aprender Java, mas dificilmente há palavras nele que não lhe sejam familiares :) Hoje, OOP é a metodologia de programação mais comum. Além do Java, os princípios OOP são usados ​​em muitas linguagens populares das quais você já deve ter ouvido falar. Estes são C++ (é usado ativamente por desenvolvedores de jogos de computador), Objective-C e Swift (eles escrevem programas para dispositivos Apple), Python (mais procurado em aprendizado de máquina), PHP (uma das linguagens de desenvolvimento web mais populares), JavaScript (mais simples, diga o que não fazem nele) e muitos outros. Na verdade, quais são esses “princípios” de OOP? Vamos contar com mais detalhes.

Princípios OOP

Este é o básico. 4 características principais que juntas formam o paradigma de programação orientada a objetos. Compreendê-los é a chave para se tornar um programador de sucesso. Princípios de programação orientada a objetos - 3

Princípio 1. Herança

A boa notícia é que você já está familiarizado com alguns dos princípios da OOP! :) Já encontramos herança algumas vezes em palestras e tivemos tempo para trabalhar com ela. Herança é um mecanismo que permite descrever uma nova classe com base em uma existente (pai). Nesse caso, as propriedades e funcionalidades da classe pai são emprestadas pela nova classe. Por que a herança é necessária e quais benefícios ela oferece? Em primeiro lugar, reutilização de código. Os campos e métodos descritos nas classes pai podem ser usados ​​nas classes descendentes. Se todos os tipos de carros possuem 10 campos comuns e 5 métodos idênticos, basta colocá-los na classe pai Auto. Você pode usá-los em classes descendentes sem problemas. Vantagens sólidas: tanto quantitativamente (menos código) quanto, como resultado, qualitativamente (as classes ficam muito mais simples). Ao mesmo tempo, o mecanismo de herança é muito flexível e você pode adicionar separadamente a funcionalidade ausente nos descendentes (alguns campos ou comportamento específico de uma classe específica). Em geral, como na vida cotidiana: somos todos semelhantes aos nossos pais em alguns aspectos, mas diferentes deles em alguns aspectos :)

Princípio 2. Abstração

Este é um princípio muito simples. Abstração significa destacar as características principais e mais significativas de um objeto e vice-versa - descartar as secundárias e insignificantes. Não vamos reinventar a roda e relembrar um exemplo de uma antiga palestra sobre aulas. Digamos que estamos criando um arquivo dos funcionários da empresa. Para criar objetos funcionários, escrevemos uma classe Employee. Quais características são importantes para sua descrição no arquivo da empresa? Nome completo, data de nascimento, número de segurança social, número de identificação fiscal. Mas é pouco provável que num cartão deste tipo precisemos da sua altura, cor dos olhos e do cabelo. A empresa não precisa dessas informações sobre o funcionário. Portanto, para a classe Employeedefiniremos as variáveis String name​​, int age, int socialInsuranceNumbere int taxNumber, e abandonaremos informações que nos são desnecessárias, como a cor dos olhos, e as abstrairemos. Mas se criarmos um catálogo de modelos fotográficos para uma agência, a situação muda drasticamente. Para descrever um modelo, a altura, a cor dos olhos e do cabelo são muito importantes para nós, mas o número TIN não é necessário. Portanto, na classe Modelcriamos variáveis String height​​, String hair, String eyes.

Princípio 3: Encapsulamento

Já o encontramos. Encapsulamento em Java significa limitar o acesso aos dados e a capacidade de alterá-los. Como você pode ver, é baseado na palavra “cápsula”. Nesta “cápsula” escondemos alguns dados importantes para nós que não queremos que ninguém altere. Um exemplo simples da vida. Você tem um nome e um sobrenome. Todo mundo que você conhece os conhece. Mas eles não têm acesso para alterar seu nome e sobrenome. Esse processo, pode-se dizer, está “encapsulado” no escritório de passaportes: lá você só pode alterar seu nome e sobrenome, e só você pode fazer isso. Outros “usuários” têm acesso somente leitura ao seu nome e sobrenome :) Outro exemplo é o dinheiro do seu apartamento. Deixá-los à vista no meio da sala não é uma boa ideia. Qualquer “usuário” (pessoa que vier até sua casa) poderá alterar o número do seu dinheiro, ou seja, Pegue-os. É melhor encapsulá-los em um cofre. Somente você terá acesso e somente com um código especial. Exemplos óbvios de encapsulamento com os quais você já trabalhou são modificadores de acesso ( private, publicetc.) e getter-setters. Se o campo ageda classe Catnão estiver encapsulado, qualquer um poderá escrever:
Cat.age = -1000;
E o mecanismo de encapsulamento nos permite proteger o campo agecom um método setter, no qual podemos verificar se a idade não pode ser um número negativo.

Princípio 4. Polimorfismo

Polimorfismo é a capacidade de tratar vários tipos como se fossem do mesmo tipo. Neste caso, o comportamento dos objetos será diferente dependendo do tipo a que pertencem. Parece um pouco complicado? Vamos descobrir agora. Vejamos o exemplo mais simples - animais. Vamos criar uma classe Animalcom um único método - voice()e dois de seus descendentes - Cate Dog.
public class Animal {

   public void voice() {

       System.out.println("Voice!");
   }
}

public class Dog extends Animal {


   @Override
   public void voice() {
       System.out.println("Bow-wow!");
   }
}

public class Cat extends Animal {

   @Override
   public void voice() {
       System.out.println("Meow!");
   }
}
Agora vamos tentar criar um link Animale atribuir um objeto a ele Dog.
public class Main {

   public static void main(String[] args) {

       Animal dog = new Dog();
       dog.voice();
   }
}
Qual método você acha que será chamado? Animal.voice()ou Dog.voice()? O método da classe será chamado Dog: Woof-woof! Criamos uma referência Animal, mas o objeto se comporta como Dog. Se necessário, ele pode se comportar como um gato, um cavalo ou outro animal. O principal é atribuir uma referência de tipo geral Animala um objeto de uma classe descendente específica. Isto é lógico, porque todos os cães são animais. Isso é o que quisemos dizer quando dissemos “os objetos se comportarão de maneira diferente dependendo do tipo que são”. Se criássemos um objeto Cat-
public static void main(String[] args) {

   Animal cat = new Cat();
   cat.voice();
}
o método voice()geraria "Meow!" O que significa “a capacidade de trabalhar com vários tipos como se fossem do mesmo tipo”? Isso também é bastante fácil. Imaginemos que estamos a criar um salão de cabeleireiro para animais. Nosso salão de cabeleireiro deve ter capacidade para cortar todos os animais, por isso vamos criar um método shear()(“cortar”) com um parâmetro Animal– o animal que vamos cortar.
public class AnimalBarbershop {

   public void shear(Animal animal) {

       System.out.println("The haircut is ready!");
   }
}
E agora podemos passar shearobjetos Cate objetos para o método Dog!
public static void main(String[] args) {

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

   AnimalBarbershop barbershop = new AnimalBarbershop();

   barbershop.shear(cat);
   barbershop.shear(dog);
}
Aqui está um exemplo claro: a classe AnimalBarbershoptrabalha com tipos Catcomo Dogse fossem do mesmo tipo. Ao mesmo tempo, eles têm um comportamento Catdiferente Dog: usam a voz de maneira diferente.

Razões para o surgimento de OOP

Por que surgiu esse novo conceito de programação - OOP ? Os programadores tinham ferramentas que funcionavam: linguagens procedurais, por exemplo. O que os levou a inventar algo fundamentalmente novo? Em primeiro lugar, a complicação das tarefas que enfrentavam. Se há 60 anos a tarefa de um programador parecia “calcular uma equação matemática tal e tal”, agora pode soar como “implementar 7 finais diferentes para o jogo STALKER dependendo das decisões que o usuário tomou nos momentos do jogo A, B, C, D , E, F e combinações dessas soluções." As tarefas, como podem ver, tornaram-se claramente mais complexas nas últimas décadas. Isso significa que os tipos de dados se tornaram mais complexos. Esta é outra razão para o surgimento da OOP. O exemplo com a equação pode ser facilmente resolvido usando primitivas comuns; nenhum objeto é necessário aqui. Mas será difícil até descrever o problema dos finais do jogo sem usar algumas classes que você inventou. Mas, ao mesmo tempo, é muito fácil descrevê-lo em classes e objetos: obviamente precisaremos da classe Game, da classe Stalker, da classe Ending, da classe Player’s Decision, da classe Game Moment e assim por diante. Ou seja, mesmo sem começar a resolver um problema, podemos facilmente imaginar “esboços” de sua solução em nossas cabeças. A crescente complexidade dos problemas forçou os programadores a dividir o problema em partes. Mas na programação processual isso não foi tão fácil. E muitas vezes o programa era uma “árvore” de um monte de galhos com todas as opções possíveis para seu funcionamento. Dependendo de certas condições, o programa foi executado em um ramo ou outro. Para programas pequenos esta opção era conveniente, mas dividir uma tarefa grande em partes era muito difícil. Essa necessidade tornou-se outra razão para o surgimento da OOP. Esse conceito deu aos programadores a capacidade de dividir um programa em vários “módulos” de classes, cada um dos quais fazia sua própria parte do trabalho. Todos os objetos, interagindo entre si, formam o trabalho do nosso programa. Além disso, o código que escrevemos pode ser reutilizado em outras partes do programa, o que também economiza muito tempo.
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION