A ideia é que o leitor, ao final do artigo, tenha um entendimento desses elementos e também como eles irão se aplicar ao C#/.NET.
A programação orientada a objetos está presente no dia-a-dia de grande parte dos desenvolvedores. Com a grande quantidade de programadores que desenvolviam em linguagens procedurais como C e Pascal, a alteração para a POO criou uma série de mitos que muitos acreditam até hoje como verdades.
Como veremos ao longo desse artigo, alguns deles são, de fato, verdades, enquanto outros são mitos que acabam sendo repetidos erroneamente.
O objetivo final é entendermos porque esses dizeres são verdades ou mitos através de exemplos utilizando a linguagem de programação C# .NET.
Ao longo desse artigo, iremos trazer uma introdução breve à programação orientada a objetos e o que ela significa no mundo de desenvolvimento. Juntamente com essa introdução, traremos alguns exemplos de linguagens orientadas a objetos comuns no mercado. Note que a implementação dos conceitos da POO irá variar de acordo com a linguagem de programação.
A seguir, iremos trazer alguns dizeres comuns a respeito da POO e analisá-los de forma detalhada através de exemplo com C#.
Programação Orientada a Objetos
Em primeiro lugar, precisamos entender que a programação orientada a objetos não é exclusividade de nenhuma linguagem de programação: trata-se de um design de software, um modelo a ser seguido. Nesse modelo, o objeto é a unidade essencial, responsável por dados e métodos para modificação do mesmo.
A grande vantagem da POO com relação a outras, como a programação procedural (ou estruturada - BOX 1), é a divisão extremamente clara entre os elementos do software. Além disso, o paradigma da orientação a objetos facilita a modelagem do software, auxiliando na criação de uma documentação muito mais completa e explicativa para a aplicação.
Essa clara divisão entre os elementos facilita na criação de aplicações modernas. A POO ainda facilita a introdução de alguns modelos de programação, como o MVC (Model-View-Controller) e o MVP (Model-View-Presenter).
A programação procedural (ou estruturada) obedece a um paradigma de programação que difere da POO em alguns pontos. Nela, os procedimentos estão ligados a dados globais, diferentemente do que vemos na POO, onde os métodos (equivalentes aos procedimentos) estão ligados aos dados do objeto.
Esse tipo de diferenciação é importante em termos da organização do software, o que traz algumas facilidades e alguns problemas.
Atualmente, linguagens estruturadas como C e Pascal são utilizadas principalmente em microcontroladores e outros elementos de programação embarcada.
O paradigma da orientação a objetos traz o conceito da abstração de objetos do mundo real. Entretanto, como veremos ao longo de nosso artigo, isso não é uma verdade absoluta. Isso é devido ao fato de que a programação orientada a objetos trouxe uma implementação um pouco diferente, baseada em classes que podem ou não ser representações da realidade.
Como um exemplo, podemos ter uma classe Carro ou Pessoa, mas também podemos ter classes que não representam um objeto real, como DadosCarro ou DadosPessoa. Essas classes, então, irão definir os objetos presentes no sistema.
Dentre os desenvolvedores, há a consciência de que uma linguagem orientada a objetos deve obedecer obrigatoriamente a quatro conceitos, considerados os pilares da POO:
- Abstração: consiste em abstrair o que queremos representar e transformá-lo em informações para serem utilizadas dentro da aplicação. Essas informações existem na forma de uma identidade (nome único da classe ou objeto), propriedades (características que definem o objeto) e métodos (ações ou eventos aos quais o objeto deve obedecer).
- Encapsulamento: consiste em esconder as informações a respeito de características e métodos de uma classe. Normalmente, esse encapsulamento é baseado em métodos especiais getters e setters, que serão considerados as propriedades da classe. O dado encapsulado é chamado, normalmente, de atributo.
- Herança: consiste em criar uma hierarquia de classes dentro da aplicação. A ideia principal aqui é a reutilização de código. Por exemplo, temos uma aplicação que possui uma classe Animal e uma classe Cachorro. O ideal é que a segunda herde informações da primeira, uma vez que se trata de um tipo específico de animal, com características a mais.
- Polimorfismo: normalmente, é tratado como uma área adjacente à herança. Isso porque o polimorfismo consiste em um objeto se comportando como vários. Em poucas palavras, linguagens que obedecem a esse conceito permitem que um objeto filho (do tipo Cachorro, para ficarmos no exemplo anterior) possa se comportar como ele mesmo (Cachorro) ou como sua classe pai (Animal, nesse caso).
Linguagens de programação orientada a objetos modernas, como C# e Java, utilizam uma artimanha muito interessante para criar aplicações capazes de executar em diferentes arquiteturas.
No caso do Java, a presença da JVM (Java Virtual Machine) garante que o software pode ser executado em diferentes máquinas. O compilador Java cria a aplicação em bytecodes capazes de serem executados por essa JVM, criando uma aplicação capaz de executar em qualquer dispositivo imaginável, em teoria.
O C# .NET utiliza uma estrutura similar, compilando a aplicação para uma linguagem intermediária de tempo de execução, que é executada pelo .NET Framework. Existem também outras abordagens, como a utilizada pelo Python.
Essa linguagem é considerada uma linguagem de script, o que significa que ela não é compilada, e sim interpretada em tempo de execução. Isso faz com que a mesma tenha uma melhor performance.
É interessante notarmos que, embora a orientação a objetos seja uma só, existe a possibilidade de diferentes interpretações. Isso faz com que surjam linguagens que são mais apropriadas para alguns tipos específicos de aplicações, como o C++, ideal para games, e o Python, muito utilizado em softwares matemáticos.
Existem elementos, porém, que veremos em todas as linguagens, e são eles que fazem des ...