Programação Orientada a Objeto (também conhecida pela sua sigla POO) ou Modelagem Orientada ao Objeto, é um modelo/paradigma de projeto e programação de software baseado na abstração digital do mundo real, através da composição e interação entre diversas unidades chamadas de 'objetos' e as classes (representando objetos reais contendo identidade, propriedades e, métodos); baseado em quatro principais componentes da programação: abstração digital, encapsulamento, herança e, polimorfismo.

Dentre as várias abordagens da POO, as baseadas em classes são as mais comuns: usando um objeto que pode ser manipulado, criado a partir de uma classe através do instanciamento. Estes possuem métodos que modificam seus próprios dados, definindo o tipo do objeto. A classe determina o comportamento (métodos), estados possíveis (atributos) e, o relacionamento com os outros objetos. A maior alternativa as classes é o uso de protótipos, onde objetos são cópias de outros, onde apenas a herança simples é implementada pela cópia.

Em alguns contextos, o termo modelagem orientada ao objeto (MOO) é preferível ao termo POO. De fato, o paradigma "orientado ao objeto" tem origem nos estudos da cognição e influenciou a inteligência artificial e a linguística, dada a relevância para a abstração de conceitos do mundo real. A MOO é considerada a melhor estratégia para diminuir o "gap semântico" (o hiato entre o mundo real e a representação digital dele), e facilita a comunicação das partes interessadas no modelo ou software (e.g. o modelador e o usuário final) na medida em que conceitos, terminologia, símbolos, grafismo e estratégias, são, potencialmente, mais óbvios, intuitivos, naturais e exatos.

Classe e protótipo Dentre as várias abordagens de orientação ao objeto, as baseadas no uso de classes são as mais comuns: esta representa um conjunto de objetos com características semelhantes; define o comportamento dos objetos através de métodos; define quais estados ele é capaz de manter através de seus atributos. Esta pode gerar subclasses que herda as todas as características.

Um objeto é algo que pode ser manipulado, é criado a partir de uma classe através do processo de programação chamado instanciamento (instanciar um objeto). Onde os objetos são operados com o conceito de 'this' (isto) ou 'self' (si), de forma que seus métodos (muitas vezes) modifiquem os dados da própria instância, que também define o tipo do objeto. Cada classe determina o comportamento (definido nos métodos) e estados possíveis (atributos) de seus objetos, assim como o relacionamento com outros objetos.

A alternativa mais usual ao uso de classes é o uso de protótipos. Neste caso, os objetos são cópias de outros objetos, e não são mais instâncias de classes; as linguagens Javascript e Lua são exemplos onde o POO é baseada em protótipos. A diferença prática mais evidente é neste tipo de POO/protótipos, apenas a herança simples é implementada pela cópia do objeto. Assim, implementa-se um conjunto de classes passíveis de serem instanciadas como objetos, por exemplo na linguagem Python e C++ - ou objetos protótipos que são copiados e alterados, por exemplo nas linguagens JavaScript e VimL).

As linguagens de programação Muitas das linguagens de programação mais utilizadas atualmente (talvez a maioria) são multi-paradigma com suporte nativo à POO, como por exemplo: C++, C#, VB.NET, Java, Object Pascal, Objective-C, Python, SuperCollider, Ruby e Smalltalk. Já as linguagens ActionScript, ColdFusion, Javascript, PHP (a partir da versão 4.0), Perl (a partir da versão 5), Visual Basic (a partir da versão 4), VimL (ou Vim script) são exemplos de linguagens de programação com suporte a orientação a objetos.

Vivacehttps://arxiv.org/abs/1502.01312 é um exemplo de linguagem sem suporte à POO.

Em direção à POO Além da programação estruturada, a POO incorpora as seguintes diretrizes: Aborde o hiato entre o problema e a linguagem compreendida pela máquina: preenche bottom-up. Use os dados como unidades básicas para construção do programa Dados e suas inter-relações são mais estáveis do que ações sobre os dados. Empacote os dados com suas operações naturais/intrínsecas Construa sob as ideias de tipos abstratos de dados Consolide os construtos que encapsulam os dados Concentre nos conceitos e fenômenos a serem manipulados Faça uso de teorias existentes de fenômenos e conceitos (bastante útil, por exemplo, para a computação natural e a inteligência artificial em geral). Forme novos conceitos a partir dos existentes Utilize um estilo de programação que permita o colapso da programação dos objetos

POO básica Tipo de Dados (TD ou simplesmente 'tipo') é um conjunto de valores que possuem propriedades em comum. Tipo abstrato de dados (TAD) é um Tipo de Dados em que o foco recai sobre a operações nos valores do tipo, em contraste com a representação destes valores. Estas operações escondem e protegem a representação dos dados enquanto facilitam o seu uso/manipulação. A POO é frequentemente compreendida e descrita como alicerçada nos TADs.

Legado de paradigmas anteriores Linguagens pré-POO (em especial as que comportavam a programação estruturada) forneceram o seguinte legado à POO: Variáveis portam informação formatada dentre um número pequeno de TDs embutidos/padrão/default e estruturas de dados derivados destes TDs básicos. Procedimentos/funções/rotinas que podem receber uma entrada, retornar uma saída, e manipular dados. Uso das estruturas de controle. Modularidade: procedimentos agrupados em arquivos e módulos, com espaços distintos de nomes para que os identificadores não entre em conflito (como o uso de namespaces).

Novas características Os atributos e métodos podem ser referentes a uma classe (e todas as suas instâncias) ou a uma única instância. O vínculo dos atributos aos métodos, de forma a manter uma interface bem definida para operação sobre os dados, e a evitar corrupção dos dados, é chamado de encapsulamento. O encapsulamento foi responsável pelo conceito de 'ocultamento de dados', central para a POO. O encapsulamento pode ser realizado através de convenções (em Python, underscores demarcam métodos e atributos protegidos e privados), ou via recursos da linguagem (em Java ou C++, um método privado só é acessado pela própria classe). Encapsulamento incentiva o desacoplamento.

Quando um objeto contém outros objetos, diz-se que há composição de objetos. A composição de objetos é usada para representar uma relação 'tem um', usualmente uma meronímia. Já a herança (quase sempre suportada pelas linguagens que utilizam classes) apresenta relações 'é um' (i.e. 'é um tipo de'), ou seja, relações de hiperonímia cujo resultado final é a árvore taxonômica. Na herança, tipicamente todos os atributos e métodos da classe pai/mãe estão também disponíveis na classe filha, embora seja comum que algumas características sejam substituídas. Assim, a herança permite reúso facilitado de características e muitas vezes reflete relações do mundo real de forma intuitiva. Ambas a 'composição de objetos' e a 'herança' constituem hierarquias entre as classes e objetos na POO.

Herança múltipla ocorre quando uma classe é filha de mais de uma classe. Mixin pode ser considerado um tipo especifico de herança, embora haja uma diferença crucial: a classe da qual são herdadas as características não é considerada pai/mãe.

Polimorfismo é quando alguma rotina pode ser chamada para objetos diferentes. Por exemplo, assuma que a função retornaCorPrincipal() possa ser chamada tanto em um objeto da classe Imagem quanto da classe Video. O polimorfismo é um tipo de abstração que simplifica códigos externos à hierarquia de classes e uma separação forte das responsabilidades (separation of concerns).

Há orientações diversas para a POO, muitas de reconhecida complexidade. Por exemplo, o princípio da composição sobre herança advoca que a composição de objetos é preferida à herança. O princípio aberto/fechado advoca que classes e funções deve ser 'abertas p extensão mas fechadas para modificação'.

Subtipos comportamentais fortes (ou princípio de substituição de Liskov, LSP do inglês Liskov substitution principle) são filhos que mantém todas as características dos pais. Dito de outra forma, seja 's' tal que todas as propriedades dos objetos t da classe T estão também presentes no objeto s da classe S, em que S é subtipo de T. Tal 's' é chamado de subtipo comportamental forte, subtipo forte, subtipo de Liskov, e variações semelhantes.

Críticas As críticas mais recorrentes à POO podem ser resumidas em:

Não satisfazer os objetivos de reusabilidade e modularidade; Enfase demasiada em design e modelamento de software, em detrimento de outros aspectos (como a computabilidade/algoritmos).; Não há consenso de que a POO realmente seja útil para modelar a realidade; É intrinsecamente menos eficiente que o código procedural, em geral demora mais para compilar (PE vs POO); A premissa de que a POO é apropriada para modelar sistemas complexos com comportamentos complexos, contrasta com o princípio KISS. Linguagens naturais não compartilham da estratégia usual na POO: 'priorizar coisas ao invés de ações', o que leva muitas vezes a representações contorcidas; Muitas vezes é realizada sem uma representação transparente do fluxo de controle (ordem das instruções), o que tem se tornado uma desvantagem com a relevância, acentuada nos últimos anos, do processamento paralelo.

Críticas de programadores notórios Joe Armstrong: "O problema com linguagens orientadas a objetos é que você tem todo esse ambiente implícito que elas levam consigo. Você queria uma banana mas o que você conseguiu foi um gorila segurando a banana e uma selva inteira."Armstrong, Joe. In Coders at Work: Reflections on the Craft of Programming. Peter Seibel, ed. Codersatwork.com, Accessed 13 November 2009.

Alexander Stepanov: "Dizer que tudo é um objeto é simplesmente dizer nada."

Steve Yegge: "Por que alguém iria tão longe para colocar um só aspecto da fala [substantivos] em um pedestal?"Stevey's Blog Rants

Eric Steven Raymond: "A POO encoraja programas com muitas camadas e destrói a transparência."

Rob Pike: "A POO constitui os números romanos da computação."

Conceitos típicos Cliente, servidor e mensagens Da passagem de mensagens entre objetos: o cliente (um objeto) emite uma mensagem para o servidor (outro objeto) em que solicita um serviço (i.e. que uma rotina qualquer seja executada) que pode implicar a emissão/retorno de uma resposta ao cliente. Um servidor pode ser cliente de outros (sub-)servidores. Esta resposta pode ser síncrona (quando o cliente aguarda a resposta do servidor para executar qualquer outra instrução) ou assíncrona (envolvendo paralelismo de atividades).

Um exemplo simples: um instituto (cliente), solicita um buffet para uma empresa especializada (servidor). Esta empresa (agora cliente) solicita salgados e sucos de outras empresas (sub-servidores). O instituto pode ficar paralisado enquanto não chega o buffet (envio síncrono de mensagem) ou continuar suas atividades (envio assíncrono de mensagem). Neste último caso, o instituto deve ser capaz de lidar com a interrupção das atividades (ou parte delas) assim que chegar o buffet.

A existência/espera de uma resposta pode ser inerente ao modelo de envio da mensagem ou ser realizada através do disparo de uma nova mensagem pelo servidor.

Responsabilidades A um servidor e seus métodos são atribuídas responsabilidades específicas. No exemplo anterior, a empresa de buffet não deve entregar um brinquedo, e a comida deve ser apropriada (não apenas várias barras de chocolate, por exemplo).

Uma responsabilidade que todos os servidores tem é a de manter seus dados consistentes. Idealmente, não deve ser possível tornar inconsistentes os dados de um objeto. Um objeto tem a responsabilidade de manter uma boa interface para se comunicar com outros objetos.