Essa será uma pergunta muito pouco técnica e não técnica, e não tenho certeza se essa é a plataforma certa. Mas eu sou um estudante iniciante em CS, então espero que vocês tolerem.
No primeiro semestre, fomos apresentados aos conceitos de OOP, como encapsulamento, ocultação de dados, modularidade, herança e assim por diante através de Java e UML. (Java é minha primeira linguagem de programação)
Pelo que entendi, OOP é uma maneira de gerenciar a complexidade do software. Mas seus princípios não são novos ou únicos, são, de certo modo, universais em todos os campos da engenharia.
Por exemplo, um carro é uma estrutura muito complexa cuja complexidade é gerenciada por uma hierarquia de componentes modulares e encapsulados com comportamentos e interfaces bem definidos.
Mas não entendo o motivo por trás da introdução de um novo paradigma de programação. Eu acho que todos os princípios usados para gerenciar a complexidade podem ser realizados por linguagens de programação procedurais. Por exemplo, para modularidade, podemos simplesmente dividir o programa em muitos pequenos programas que executam tarefas bem definidas, cujo código está contido em arquivos separados. Esses programas interagem entre si por meio de entradas e saídas bem definidas. Os arquivos podem ser protegidos (criptografados?) Para obter o encapsulamento. Para reutilização de código, podemos chamar esses arquivos sempre que forem necessários em novos programas. Isso não captura tudo o que é OOP ou estou perdendo algo muito óbvio?
Não estou pedindo uma prova de que OOP gerencia a complexidade. Na minha opinião, certamente faz. Mas acho que todos os princípios usados para gerenciar a complexidade, como modularidade, encapsulamento, ocultação de dados etc. podem ser facilmente implementados por linguagens procedurais. Então, por que realmente fazer POO se podemos gerenciar a complexidade sem ela?
fonte
Respostas:
Deixe-me tentar com uma resposta muito baixa da teoria :)
O que você realmente está perguntando é: Por que incluir suporte à Orientação a Objetos (OO) diretamente no idioma quando linguagens procedurais podem ser usadas para criar e escrever código OO?
E a resposta é: Ter um padrão de como o OO é expresso no código-fonte, para que você não termine com 22 implementações diferentes para a mesma abstração.
Por exemplo, digamos que eu crie um
MagicButton
e umMagicSlider
que possa ser usado em um sistema de interface com o usuário. Eu preciso de uma maneira de agrupar os métodos que podem ser usados com o MagicButton, os métodos que só podem ser usados com o MagicSlider e os métodos que podem ser usados por ambos. Esses objetos compartilham alguns métodos porque são ambos objetos mágicos da GUI.Eu posso fazer o agrupamento nomeando funções de uma maneira especial
MagicSlider_DoSomething ...
, incluindo os métodos em arquivos específicos nomeados de uma maneira especialMagicSliderMethods.XXX
, ou eu poderia encontrar outra maneira especial de fazer a mesma coisa. Se não houver uma maneira padrão no idioma para fazê-lo, farei diferente de você e de qualquer outra pessoa. Isso torna o compartilhamento de código muito mais difícil.Sim, o envio tardio - métodos virtuais em linguagens OO - pode ser implementado em linguagens procedurais, mas existem muitas maneiras diferentes de implementá-lo. Dependendo de quem escreveu o código, você terminará com diferentes implementações de OO dentro do mesmo programa.
Pense no pobre desenvolvedor de manutenção. Essa pessoa deve gerenciar diferentes abstrações de objetos e maneiras diferentes de chamar métodos virtuais, dependendo de quem escreveu o código original.
Além disso: ter as abstrações no idioma permite que editores de código avançados, como o Eclipse, façam muitas análises estáticas no código. Por exemplo, o Eclipse pode oferecer uma lista de todos os métodos que podem ser usados em um objeto, bem como a implementação automática de "métodos TODO" vazios. O Eclispe sabe exatamente quais métodos sua classe deve implementar com base em quais classes você estende e em quais interfaces você implementa. Isso seria quase impossível se não houvesse um padrão de linguagem para fazer OO.
fonte
Nenhum desses são conceitos de POO. Todos eles existem fora do OO, independentemente do OO e muitos até foram inventados antes do OO.
Então, se você acha que é disso que se trata o OO, sua conclusão é correta: você pode fazer tudo isso em linguagens processuais, porque eles não têm nada a ver com o OO .
Por exemplo, um dos documentos seminais sobre Modularidade é Sobre os critérios a serem usados na decomposição de sistemas em módulos . Não há menção de OO lá. (Foi escrito em 1972, então o OO ainda era um nicho obscuro, apesar de já ter mais de uma década.)
Embora a Abstração de Dados seja importante no OO, é mais uma consequência do recurso principal do OO (Sistema de Mensagens) do que um recurso definidor. Além disso, é muito importante lembrar que existem diferentes tipos de abstração de dados. Os dois tipos mais comuns de abstração de dados em uso atualmente (se ignorarmos "nenhuma abstração", que provavelmente ainda é usada mais do que as outras duas combinadas) são tipos e objetos de dados abstratos . Assim, apenas dizendo "Information Hiding", "Encapsulation" e "Data Abstraction", você não disse nada sobre OO, pois OO é apenas uma forma de Abstração de Dados, e as duas são de fato fundamentalmente diferentes:
A propósito, o que isso significa é que, em Java, as classes não são orientadas a objetos. Duas instâncias da mesma classe podem acessar a representação e a implementação privada uma da outra. Portanto, instâncias de classes não são objetos, na verdade são instâncias ADT. Java
interface
s, no entanto, não fornecem abstração de dados orientado a objetos. Portanto, em outras palavras: apenas instâncias de interfaces são objetos em Java, instâncias de classes não.Basicamente, para tipos, você só pode usar interfaces. Isso significa tipos de parâmetros de métodos e construtores, tipos de métodos de retorno, tipos de campos de instância, campos estáticos e campos locais, o argumento para um
instanceof
operador ou operador de conversão e argumentos de tipo para um construtor de tipo genérico sempre devem ser interfaces. Uma classe pode ser usada apenas diretamente após onew
operador, em nenhum outro lugar.O que você descreve é OO.
Essa é realmente uma boa maneira de pensar sobre OO. De fato, isso é exatamente o que os inventores originais da OO tinham em mente. (Alan Kay foi um passo além: ele imaginava muitos computadores pequenos enviando mensagens entre si pela rede.) O que você chama de "programa" geralmente é chamado de "objeto" e, em vez de "chamada", costumamos dizer "enviar uma mensagem" "
Orientação a Objetos tem tudo a ver com Mensagens (também conhecido como despacho dinâmico ). O termo "Orientado a Objetos" foi cunhado pelo Dr. Alan Kay, o principal designer do Smalltalk, e ele o define assim :
Vamos detalhar isso:
Em termos de implementação, o sistema de mensagens é uma chamada de procedimento com limite tardio e, se as chamadas de procedimento são limitadas com atraso, não é possível saber em tempo de design o que você chamará, portanto, não é possível fazer suposições sobre a representação concreta do estado. Então, realmente se trata de mensagens, a ligação tardia é uma implementação de mensagens e o encapsulamento é uma conseqüência disso.
Mais tarde, ele esclareceu que " a grande idéia é ' enviar mensagens' " e lamenta tê-la chamado de "orientado a objetos" em vez de "orientado a mensagens", porque o termo "orientado a objetos" coloca o foco na coisa sem importância (objetos ) e distrai o que é realmente importante (mensagens):
(É claro que hoje em dia a maioria das pessoas nem se concentra nos objetos, mas nas classes, o que é ainda mais errado.)
As mensagens são fundamentais para o OO, tanto como metáfora quanto como mecanismo.
Se você envia uma mensagem a alguém, não sabe o que ela faz. A única coisa que você pode observar é a resposta deles. Você não sabe se eles próprios processaram a mensagem (por exemplo, se o objeto possui um método), se encaminharam a mensagem para outra pessoa (delegação / proxy), se eles a entenderam. É disso que se trata o encapsulamento, do OO. Você não pode nem distinguir um proxy do real, desde que ele responda como você espera.
Um termo mais "moderno" para "sistema de mensagens" é "envio dinâmico de método" ou "chamada virtual de método", mas que perde a metáfora e se concentra no mecanismo.
Portanto, existem duas maneiras de analisar a definição de Alan Kay: se você a considerar por conta própria, poderá observar que as mensagens são basicamente uma chamada de procedimento de ligação tardia e a ligação tardia implica encapsulamento, para que possamos concluir que # 1 e # 2 são realmente redundantes, e OO é tudo sobre ligação tardia.
No entanto, mais tarde ele esclareceu que o importante é o envio de mensagens e, portanto, podemos vê-lo de um ângulo diferente: o envio de mensagens é tardio. Agora, se as mensagens fossem a única coisa possível, o número 3 seria trivialmente verdadeiro: se houver apenas uma coisa, e essa coisa for atrasada, todas as coisas serão atrasadas. E mais uma vez, o encapsulamento segue as mensagens.
Pontos semelhantes também são apresentados em On Understanding Data Abstraction, revisitado por William R. Cook e também em sua Proposta de definições modernas e simplificadas de "Objeto" e "Objeto Orientado" :
No Smalltalk-72, não havia nenhum objeto! Havia apenas fluxos de mensagens que foram analisados, reescritos e redirecionados. Primeiro vieram os métodos (maneiras padrão de analisar e redirecionar os fluxos de mensagens), depois vieram os objetos (agrupamentos de métodos que compartilham algum estado privado). A herança veio muito mais tarde, e as classes foram introduzidas apenas como uma maneira de apoiar a herança. Se o grupo de pesquisa de Kay já soubesse sobre protótipos, eles provavelmente nunca teriam introduzido aulas em primeiro lugar.
Benjamin Pierce, em Tipos e linguagens de programação, argumenta que o recurso definidor da orientação a objetos é a recursão aberta .
Então: de acordo com Alan Kay, OO é tudo sobre mensagens. De acordo com William Cook, OO tem tudo a ver com o envio de método dinâmico (que é realmente a mesma coisa). De acordo com Benjamin Pierce, OO é tudo sobre Open Recursion, o que basicamente significa que as referências automáticas são resolvidas dinamicamente (ou pelo menos é uma maneira de pensar), ou, em outras palavras, mensagens.
Como você pode ver, a pessoa que cunhou o termo "OO" tem uma visão bastante metafísica dos objetos, Cook tem uma visão bastante pragmática e Pierce uma visão matemática muito rigorosa. Mas o importante é: o filósofo, o pragmatista e o teórico concordam! As mensagens são o único pilar da OO. Período.
Observe que não há menção de herança aqui! A herança não é essencial para o OO. Em geral, a maioria das linguagens OO tem algum modo de reutilização da implementação, mas isso não necessariamente tem que ser herança. Também poderia ser uma forma de delegação, por exemplo. De fato, o Tratado de Orlando discute a delegação como uma alternativa à herança e como diferentes formas de delegação e herança levam a diferentes pontos de design no espaço de design das linguagens orientadas a objetos. (Observe que, mesmo em linguagens que suportam herança, como Java, as pessoas são ensinadas a evitá-la, indicando novamente que não é necessário para o OO).
fonte
Quando você diz "muito facilmente", está fazendo uma afirmação muito ousada. O jeito que eu li é: "Não vejo dificuldade, então não deve ser muito grande". Quando formulado dessa maneira, fica claro que você não está perguntando "por que precisamos de OO", mas sim "por que as dificuldades encontradas por outros paradigmas de programação que levam à invenção do OO são imediatamente aparentes para mim?" "
Uma resposta para essa pergunta é que muitas dessas dificuldades não existem nos tipos de programas em que você está trabalhando. Você não está sendo solicitado a atualizar o código de espaguete de 40 anos. Você não está tentando escrever um novo gerenciador de exibição para um sistema operacional. Você não está depurando aplicativos distribuídos multithread.
Para muitos dos tipos de programas de brinquedo que nós, estudantes de CS, somos incumbidos de escrever, podemos escrevê-los no BASIC ou na montagem, como Java ou Python. Isso ocorre porque a complexidade inerente das tarefas é muito baixa, existe apenas um desenvolvedor, não há problemas de interoperabilidade herdados, o desempenho não importa e o código provavelmente será executado apenas algumas vezes em uma máquina.
Imagine pegar um estudante e pedir para eles se fundirem em uma rua movimentada na hora do rush, em uma transmissão manual sem sincronização, subindo uma colina íngreme. Desastre. Por quê? Eles não conseguem gerenciar o nível de complexidade necessário para seguir simultaneamente todas as regras exigidas pela tarefa.
Agora imagine o mesmo aluno, o mesmo veículo, dirigindo a passos largos em um estacionamento vazio. Eles estão bem, porque seu nível de habilidade é adequado à tarefa. Não há pressão, pouco risco, e eles podem realizar as subtarefas individuais de partida, embreagem, mudança, aceleração e direção, uma de cada vez.
Esse aluno pode perguntar por que temos transmissões automáticas, se um motorista experiente pode fazer todas essas coisas simultaneamente? A resposta é que um motorista habilidoso não precisa, em condições ideais, de um automático. Mas nem todos somos condutores profissionais em perfeitas condições e normalmente queremos a conveniência de ter os projetistas do carro cuidando de toda essa complexidade para nós.
Um programador qualificado e disciplinado o suficiente pode realmente criar um sistema de alta complexidade em C ou montagem. Mas não somos todos Linus Torvalds. Nem devemos ter que ser, para criar software útil.
Pessoalmente, não tenho interesse em ter que reinventar todos os recursos de uma linguagem moderna antes que eu possa resolver o problema em questão. Se eu posso tirar proveito de uma linguagem que inclui soluções para problemas já resolvidos, por que não?
Então, eu mudarei sua pergunta e perguntarei se as linguagens oferecem recursos convenientes, como encapsulamento e polimorfismo, por que não devemos usá-las?
fonte
O que você está descrevendo não é OOP, é abstração. A abstração está presente em todos os modelos modernos de design, mesmo aqueles que não são OOP. E OOP é um tipo muito específico de abstração.
Primeiro, vale a pena notar que não há uma definição única de OOP, portanto, pode haver pessoas que discordam do que estou caracterizando como OOP.
Em segundo lugar, é importante lembrar que o OOP foi inspirado nos modelos tradicionais de design; portanto, as semelhanças com o design do carro não são coincidência.
No entanto, aqui estão algumas maneiras pelas quais o OOP é mais matizado do que você disse:
Encapsulamento: não se trata apenas de ter uma interface definida para um módulo (ou seja, abstração), mas de proibir o acesso além dessa interface. Em Java, acessar uma variável privada é um erro de compilação, enquanto no design do seu carro, você pode (em alguns casos) usar as coisas de uma maneira diferente da interface pretendida.
Herança: Isso é realmente o que torna o OOP único. Depois de definir uma interface, você pode fazer várias coisas implementando essa interface e fazer isso de maneira hierárquica, alterando partes específicas de sua implementação e herdando todas as partes anteriores, reduzindo enormemente a duplicação de código.
Se você pensa em termos dos componentes encapsulados de um carro, não há realmente um equivalente a isso. Não há como eu fazer uma engrenagem, pegando uma engrenagem diferente e alterando uma parte específica de sua implementação. (Pelo menos acho que não, não sei muito sobre carros).
Polimorfismo : Depois de definir uma interface, qualquer coisa que use essa interface deve ser indistinguível, do ponto de vista de quais operações estão disponíveis, e você não precisa saber qual implementação está sendo usada para usar uma interface. É aqui que a subtipagem e o Princípio da Substituição de Liskov se tornam importantes.
Acoplamento : Um aspecto fundamental do OOP é que relacionamos as coisas com as mesmas operações e espalhamos as diferentes formas que elas podem ter. Os dados são empacotados com operações nesses dados. Isso significa que é muito fácil adicionar uma nova forma de dados (uma nova implementação), mas muito difícil adicionar uma nova operação a uma interface (já que você precisaria atualizar cada classe que implementa a interface). Isso contrasta com os tipos de dados algébricos em linguagens funcionais, onde é muito fácil adicionar uma nova operação (você acabou de escrever uma função que lida com todos os casos), mas difícil adicionar uma nova variante (já que você precisa adicionar uma nova caso a todas as suas funções).
fonte
Isso depende do significado da palavra "necessidade".
Se "necessidade" significa requer, não, nós não exigimos.
Se "necessidade" significa "fornece fortes benefícios", então eu diria "Sim", nós o desejamos.
Quadro grande
Os idiomas OO vinculam funcionalidade aos dados.
Você pode evitar essa ligação e funções de gravação que transmitem valores de dados.
Mas então você provavelmente terminará com constelações de dados que combinam e começará a distribuir tuplas, registros ou dicionários de dados.
E, na verdade, são todas as chamadas de métodos: funções parciais em conjuntos de dados vinculados.
Recurso por recurso
Recursos do OOP:
No entanto, nenhuma dessas coisas acontece tão facilmente quanto em uma linguagem orientada a objetos com suporte de primeira classe a esses recursos.
Referências
Existem muitos críticos de OOP .
No entanto, estudos parecem indicar que obtemos maior produtividade do programador da reutilização de código por meio do OOP. Esta é uma descoberta controversa, e alguns pesquisadores dizem que não podem reproduzir esses ganhos de produtividade, dadas certas restrições. (fonte)
Conclusão
Nós não "precisamos" de POO. Mas, em alguns casos, o usuário deseja POO.
Meu entendimento é que programadores maduros podem ser bastante produtivos no estilo orientado a objetos. E quando os pacotes têm objetos principais com interfaces simples que são facilmente compreendidas, até novos programadores podem se tornar bastante produtivos rapidamente.
fonte
Vou tentar ser breve.
O princípio central do OO é a combinação de dados e comportamento em uma única unidade organizacional (um objeto).
Isso é o que nos permite controlar a complexidade e era um conceito bastante inovador quando surgiu. Compare isso com os arquivos, por um lado (dados puros), os programas que lêem e processam esses arquivos, por outro lado (lógica pura) e a saída (dados puros novamente).
Somente quando você tiver esse pacote de dados e lógica juntos, modelando alguma entidade do mundo real, você poderá começar a trocar mensagens, criar classes-filhos, separar dados e comportamentos públicos e privados, implementar comportamentos polimórficos e fazer toda essa mágica específica de OO.
Então, sim, OO é um grande negócio. E não, não é apenas um monte de coisas antigas com um nome chique.
Desmontar tudo, olhar para os elementos e depois dizer "oh, bem, não há nada aqui que eu não tenha visto antes" não é reconhecer a montagem que sustenta a inovação. O resultado é mais do que a soma de suas partes.
fonte
Não existe uma definição "oficial" de programação orientada a objetos, e pessoas razoáveis discordam do que realmente está definindo a qualidade do OO. Alguns dizem que mensagens, outros dizem subtipos, outros dizem herança, outros dizem que o agrupamento de dados e comportamento. Isso não significa que o termo não tenha sentido, apenas que você não deve ficar muito envolvido em discussões sobre o que é o verdadeiro OO.
Encapsulamento e modularidade são princípios mais fundamentais do design e devem ser aplicados em todos os paradigmas de programação. Os defensores do OO não afirmam que essas propriedades só podem ser alcançadas com o OO - apenas que o OO é particularmente adequado para isso. É claro que os proponentes de outros paradigmas, como a programação funcional, afirmam o mesmo para o seu paradigma. Na prática, muitas linguagens de sucesso são multiparadigma e o OO, funcional etc. deve ser visto como ferramenta, e não como "o único caminho verdadeiro".
Verdade, porque no final você pode fazer qualquer coisa em qualquer linguagem de programação. Pode ser mais fácil em alguns idiomas do que em outros, pois todos os idiomas têm pontos fortes e fracos diferentes.
fonte
Algo que as outras respostas não mencionaram: estado.
Você fala sobre OO como uma ferramenta para gerenciar a complexidade . O que é complexidade? Esse é um termo confuso. Todos nós temos esse senso gestalt do que isso significa, mas é mais difícil identificá-lo. Poderíamos medir a complexidade ciclomática, ou seja, o número de caminhos de tempo de execução através do código, mas não sei sobre o que estamos falando quando usamos o OO para gerenciar a complexidade.
O que acho que estamos falando é da complexidade relacionada ao estado.
Há duas idéias principais por trás do encapsulamento . Um deles, a ocultação de detalhes de implementação , é bastante bem coberto nas outras respostas. Mas outro está escondendo seu estado de tempo de execução . Não mexemos nos dados internos dos objetos; passamos mensagens (ou chamamos métodos, se você preferir os detalhes da implementação do que o conceito, como Jörg Mittag apontou). Por quê?
As pessoas já mencionaram isso porque você não pode alterar a estrutura interna dos seus dados sem alterar o código que os acessa, e você deseja fazer isso em um local (o método acessador) em vez de 300 locais.
Mas também é porque torna o código difícil de raciocinar : o código processual (seja em uma linguagem de natureza processual ou simplesmente escrita nesse estilo) oferece pouca ajuda para impor restrições à mutação de estado. Qualquer coisa pode mudar a qualquer momento e de qualquer lugar. As funções / métodos de chamada podem ter ação assustadora à distância. O teste automatizado é mais difícil, pois o sucesso dos testes é determinado pelo valor de variáveis não locais que são amplamente acessadas / acessíveis.
Os outros dois grandes paradigmas de programação (OO e funcional) oferecem soluções interessantes, mas quase diametralmente opostas, para o problema da complexidade relacionada ao estado. Na programação funcional, tenta-se evitá-lo completamente: as funções são geralmente puras, as operações nas estruturas de dados retornam cópias em vez de atualizar o original no local, etc.
OO, por outro lado, oferece ferramentas para lidar com o gerenciamento de estado (em vez de ferramentas para evitá-lo). Além das ferramentas no nível do idioma, como modificadores de acesso (protegido / público / privado), getters e setters, etc., também existem várias convenções relacionadas, como a Lei de Demeter, que desaconselha o alcance de objetos para obter dados de outros objetos. .
Observe que você não precisa de objetos para fazer realmente nada disso: você pode ter um fechamento com dados inacessíveis e retornar uma estrutura de dados de funções para manipulá-los. Mas isso não é um objeto? Isso não se encaixa intuitivamente na nossa concepção do que é um objeto? E se tivermos esse conceito, não é melhor repeti-lo na linguagem, em vez de (como outras respostas disseram) depender de uma explosão combinatória de implementações ad-hoc concorrentes?
fonte
Não. Mas eles podem ajudar em muitas situações.
Eu uso principalmente uma única linguagem OO há décadas, mas a maior parte do meu código é realmente estritamente pré-OO. No entanto, para qualquer coisa que envolva uma GUI, uso a vasta biblioteca OO da linguagem de métodos e objetos internos, porque simplifica tremendamente o meu código.
Por exemplo, um aplicativo do Windows que usa a API original do Windows de baixo nível para exibir um formulário, um botão e um campo de edição requer muito código; ao invés disso, o uso das bibliotecas de objetos que acompanham o Visual Basic ou C # ou Delphi fazem o mesmo programa minúsculo e trivial. Portanto, meu código OO geralmente é relativamente pequeno e para a GUI, enquanto o código que esses objetos chamam geralmente é muito maior e geralmente não se preocupa em ser OO (embora possa variar dependendo do problema que estou tentando resolver).
Eu já vi programas de OO muito complicados, baseados em regras esotéricas complicadas sobre como os objetos foram implementados e poderiam ser muito mais simples se escritos sem os conceitos de OO. Eu também vi o oposto: sistemas complexos que clamam por serem reimplementados e simplificados usando objetos.
À medida que você ganha experiência, descobre que situações diferentes exigem ferramentas e soluções diferentes, e um tamanho não serve para todos.
fonte
Como alguém que está envolvido em um projeto muito grande inteiramente escrito em C, posso definitivamente dizer que a resposta é um claro "não".
A modularidade é importante. Mas a modularidade pode ser implementada em praticamente qualquer linguagem decente. Por exemplo, C suporta compilação modular, arquivos de cabeçalho e tipos de estrutura. Isso é suficiente para 99% dos casos. Defina um módulo para cada novo tipo de dados abstratos necessário e defina as funções para operar no tipo de dados. Às vezes, você deseja desempenho e essas funções estão no arquivo de cabeçalho como funções embutidas; outras vezes, você usará funções padrão. É tudo invisível para o usuário de que maneira é escolhida.
Estruturas suportam composição. Por exemplo, você pode ter uma tabela de hash bloqueada que consiste em um bloqueio mutex e uma tabela de hash regular. Isso não é programação orientada a objetos; nenhuma subclasse é feita. A composição é uma ferramenta muito mais antiga que a idéia de programação orientada a objetos.
Para 1% dos casos em que a modularidade no nível de compilação não é suficiente e você precisa de modularidade no tempo de execução, existe uma coisa chamada ponteiros de função. Eles permitem ter implementações individuais de uma interface bem definida. Observe que isso não é programação orientada a objetos em uma linguagem não orientada a objetos. Isso está definindo uma interface e, em seguida, implementando-a. Por exemplo, a subclasse não é usada aqui.
Considere talvez o projeto de código aberto mais complexo que existe. Ou seja, o kernel do Linux. Está escrito inteiramente na linguagem C. Isso é feito principalmente usando as ferramentas de modularidade de nível de compilação padrão, incluindo composição e, ocasionalmente, sempre que a modularidade de tempo de execução é necessária, ponteiros de função são usados para definir e implementar uma interface.
Se você tentar encontrar um exemplo de programação orientada a objetos no kernel do Linux, tenho certeza de que é muito difícil encontrar esse exemplo, a menos que você estenda a programação orientada a objetos para incluir tarefas padrão como "definir uma interface e implementá-la".
Observe que mesmo a linguagem de programação C suporta programação orientada a objetos, se você realmente precisar. Por exemplo, considere o kit de ferramentas da interface gráfica do usuário GTK. Na verdade, é orientado a objetos, embora escrito em uma linguagem não orientada a objetos. Portanto, isso mostra que a idéia de que você precisa de uma "linguagem orientada a objetos" é profundamente falha. Não há nada que uma linguagem orientada a objetos possa fazer que outro tipo de linguagem não possa fazer. Além disso, se você é um programador especialista, sabe como escrever código orientado a objetos em qualquer idioma com muita facilidade. Não é um fardo usar C, por exemplo.
Portanto, as conclusões são de que as linguagens orientadas a objetos provavelmente são úteis apenas para programadores iniciantes que não conseguem entender como o conceito é realmente implementado. No entanto, eu não gostaria de estar perto de qualquer projeto em que os programadores sejam programadores iniciantes.
fonte
A razão para introduzir paradigmas de programação, incluindo métodos orientados a objetos, é facilitar a criação de programas mais sofisticados e poderosos. Na edição de agosto de 1981 da Byte Magazine, Daniel Ingalls , um dos principais criadores do Smalltalk, definiu "orientado a objetos" como envolvendo os seguintes recursos:
Esses foram os princípios que Ingalls identificou como as principais considerações de design do SmallTalk-80, desenvolvido pela Xerox Parc Research. No artigo da revista acima mencionado, você pode ler uma descrição detalhada de cada um desses princípios e como eles contribuem para o paradigma orientado a objetos, de acordo com Ingalls.
Todos esses princípios podem ser aplicados usando qualquer linguagem completa de Turing, seja processual, linguagem assembly ou qualquer outra coisa. Estes são princípios de design, não uma especificação de linguagem. Uma linguagem orientada a objetos visa facilitar o uso desses princípios ao criar software.
Por exemplo, para adotar o primeiro dos princípios da Ingall (gerenciamento automático de armazenamento), qualquer pessoa pode escrever seu próprio sistema de gerenciamento automático de armazenamento em uma linguagem processual, mas seria muito trabalhoso fazê-lo. Ao usar uma linguagem como SmallTalk ou Java que possui gerenciamento de armazenamento automático embutido, o programador não precisa trabalhar tanto para gerenciar a memória. A desvantagem é que o programador obtém menos controle sobre o modo como a memória é usada. Portanto, há um benefício e uma desvantagem. A idéia de um paradigma de design como a programação orientada a objetos é que os benefícios do paradigma superam as desvantagens de pelo menos alguns programadores.
fonte
Uma maneira de gerenciar a complexidade do software é separar completamente a estrutura das ações desejadas usando um idioma específico do domínio . Isso significa que o nível do código de programação é distinto do nível em que os resultados desejados são configurados - uma linguagem ou sistema completamente diferente. Quando isso é feito corretamente, o código convencional torna-se essencialmente uma biblioteca e o usuário ou outra pessoa que cria os resultados desejados conecta as coisas a uma linguagem de script ou ferramenta de design visual, como um gerador de relatórios.
Para funcionar, isso requer o estabelecimento de um limite estrito em torno de quais operações serão possíveis e como elas serão vinculadas (linguagem de script ou design visual, como uma ferramenta de construção de formulário). Os metadados são uma maneira importante de abstrair a configuração de tempo de execução dos detalhes de codificação, possibilitando que um sistema suporte uma ampla variedade de resultados desejados. Se os limites forem definidos e mantidos (não aceitando todas as solicitações de extensão que surgirem), você poderá ter um sistema robusto e duradouro que funcione para as pessoas, sem que elas precisem ser programadores para realizar o que desejam.
Martin Fowler escreveu um livro sobre isso, e a técnica é quase tão antiga quanto a própria programação. Você quase poderia dizer que todas as linguagens de programação são linguagens específicas do domínio e, portanto, a idéia é endêmica, esquecida por ser tão óbvia. Mas você ainda pode criar suas próprias ferramentas de script ou design visual para facilitar sua vida. Às vezes, generalizar um problema facilita muito a solução!
fonte
Esta é uma pergunta muito boa e considero que as respostas dadas aqui não fizeram justiça, por isso irei adiante e acrescentarei meus pensamentos.
O objetivo é - Gerenciar a complexidade do software . O objetivo não é "usar linguagem OO".
Não há razão para a introdução de um novo paradigma. É algo que aconteceu naturalmente quando a codificação se tornou mais madura. Faz mais sentido escrever código onde adicionamos um coach no final do trem (o trem sendo modelado usando uma lista vinculada) em vez de adicionar um novo nó ao final da lista vinculada.
Codificação em termos de entidades do mundo real é simplesmente a maneira mais óbvia e correcta para codificar quando são codificação sobre as entidades do mundo real.
Um computador pode trabalhar com a adição de um nó ao final da lista vinculada tão facilmente quanto com a adição de um coach extra ao final do trem. Mas para os seres humanos é mais fácil trabalhar com o trem e o treinador do que com a lista e os nós vinculados, embora quando formos um nível profundo, encontramos o trem sendo modelado por meio de uma lista vinculada.
Proteger ou criptografar os arquivos não pode alcançar o encapsulamento. O oposto da criptografia é descriptografia. O oposto do encapsulamento é Decapsulation, que significa decomposição de estruturas e classes em linguagens de programação para obter melhor desempenho. O desempenho obtido com a redução do tráfego de memória e a evitar verificações de regras OOP.
Portanto, você pode escrever um código que seja criptografado e bem encapsulado, porque esses dois são conceitos diferentes.
O encapsulamento ajuda a gerenciar a complexidade em virtude de estar próxima da realidade.
Portanto, programe em objetos porque é mais fácil para você codificar e é mais rápido para você e todos os outros entenderem.
fonte
A única coisa a lembrar é o seguinte:
OOP não é sobre recursos de linguagem; é sobre a maneira como você estrutura seu código .
OOP é uma maneira de pensar e projetar a arquitetura do seu código, e isso pode ser feito em praticamente qualquer idioma. Isso inclui especialmente aquelas linguagens de baixo nível e não OO, chamadas assembler e C. Você pode executar uma programação perfeitamente orientada a objetos no assembler, e o kernel Linux, escrito em C, é bastante orientado a objetos em muitos aspectos. .
Dito isso, os recursos de OO em um idioma reduzem bastante a quantidade de código padrão que você precisa escrever para alcançar os resultados desejados . Onde você precisa definir explicitamente uma tabela de função virtual e preenchê-la com os ponteiros de função apropriados em C, você simplesmente não faz nada em Java e está pronto. As linguagens OO simplesmente removem tudo o que habilita o cruft do código-fonte, escondendo-o por trás de abstrações agradáveis no nível da linguagem (como classes, métodos, membros, classes base, chamadas implícitas de construtor / destruidor, etc.).
Portanto, não, não precisamos de idiomas OO para fazer OOP. Só que OOP é muito mais fácil de fazer com uma linguagem OO decente.
fonte
A programação orientada a objetos é mais do que apenas módulos + encapsulamento. Como você diz, é possível usar módulos + encapsulamento em uma linguagem não-orientada a objetos (procedural). OOP envolve mais do que apenas isso: envolve objetos e métodos. Então, não, isso não captura OOP. Veja, por exemplo, https://en.wikipedia.org/wiki/Object-oriented_programming ou uma boa introdução a OOP de um livro didático.
fonte
O maior motivo é que, à medida que um programa se torna mais complexo, você precisa tornar invisíveis algumas partes dele, ou a complexidade do aplicativo e o número de funções farão o seu cérebro escorrer pelos ouvidos.
Vamos imaginar um sistema de 100 classes, cada uma com cerca de 20 operações que podem ser executadas nelas; isso é 2.000 funções. No entanto, desses, talvez apenas 500 sejam operações completas como 'Salvar' e 'Excluir', enquanto 1500 são funções internas que executam um pouco de manutenção ou têm alguma função de utilidade. Considerar;
Assim,
SetName
é uma função que as pessoas deveriam estar desempenhando com uma pessoa, masSplitPersonName
é uma função utilitária usada pela pessoa.A programação procedural direta não faz distinção entre essas duas operações. Isso significa que seus 2.000 funcionais disputam sua atenção. No entanto, se pudéssemos marcar essas funções como 'disponíveis para todos que possuem um registro pessoal' e 'usadas apenas como uma função utilitária dentro do registro pessoal', nossa atenção agora é de 500 'disponíveis para todas as funções' e 15 'utilitários' funções para a turma que você está editando.
Isso é o que
public
eprivate
fazer;fonte