As exceções são um conceito de POO?

37

Depois de ler um post ontem, percebi que não sabia muito sobre a origem das exceções. É apenas um conceito relacionado ao POO? Costumo pensar que sim, mas novamente existem exceções no banco de dados.

João V
fonte
Uma vez eu li que um "Sr. Goodenuf" (ou similar) inventou exceções em resposta a "não importa, é Goodenuf, hein!" bullying de estilo. Parece que não consigo encontrar uma referência agora - talvez alguém possa encontrar. Seria interessante saber em qual idioma eles foram adicionados primeiro.
Steve314
7
Haskell tem exceções e não é OOP
Daniel Gratzer
1
Embora as próprias exceções não sejam estritamente orientadas a objetos, a prática comum de definir exceções como objetos e de lançar e capturar instâncias desses objetos claramente é muito POO.
Dougvj
Qual é a diferença entre uma exceção e um GOTO seria uma pergunta interessante.
Austin Henley
2
@ Austin - que tal ", embora os lançamentos de exceção violem o princípio do ponto de saída único que alguns dos discípulos mais estritos da programação estruturada advogam como absoluto, eles não permitem o fluxo irrestrito de controle de espaguete da maneira que o gotofazem. Em particular, o alvo de o arremesso é determinado pelo contexto, com base no aninhamento de estruturas de blocos. Assim, as exceções dependem até de uma forma um pouco menos rigorosa de programação estruturada, na qual o princípio de saída única é tomado como orientação, mas não como absoluto ".
Steve314

Respostas:

5

Exceções não são um conceito de POO.

Mas eles não são completamente independentes, nem em um pequeno ponto minúsculo.

Como outras respostas mostraram: O conceito de exceções chegou a vários idiomas que não são OOP. Nada nesse conceito requer algo do OOP.

Mas todas as linguagens OOP, se não todas, que levam a sério a OOP exigem exceções, porque os outros métodos de tratamento de erros falham em um ponto específico: O construtor.

Um dos pontos do POO é que um objeto deve encapsular e gerenciar seu estado interno de forma completa e consistente. Isso também significa que, em OOP puro, você precisa de um conceito para criar um novo objeto com um estado consistente "atomicamente" - tudo, desde a alocação de memória (se necessário) até a inicialização até um estado significativo (por exemplo, zerar a memória não é suficiente) deve ser feito em uma expressão. Portanto, um construtor é necessário:

Foo myFoo = Foo("foo", "bar", 42);

Mas isso significa que o construtor também pode falhar devido a algum erro. Como propagar as informações de erro do construtor sem exceções?

  • Valor de retorno? Falha, já que em alguns idiomas newpoderia retornar apenas, nullmas não nenhuma informação significativa. Em outras línguas (por exemplo, C ++) myFoonão é um ponteiro. Você não pode verificar null. Além disso, você não pode perguntar myFoosobre o erro - ele não foi inicializado e, portanto, "não existe" no pensamento OOP.

  • Sinalizador de erro global? Tanto sobre o estado de encapsulamento e algumas variáveis ​​globais? Vá para h ... ;-)

  • Uma mistura? De maneira alguma melhor.

  • ?

Portanto, as exceções são um conceito mais fundamental que o POO, mas o POO se baseia nelas de maneira natural.

AH
fonte
3
Até onde eu sei, a única palavra nesta "resposta" que aborda a questão real é "não". O resto parece ser sobre exceções em OOP - com o devido respeito para mim esta lê em algum lugar entre vagamente relacionados e totalmente irrelevante - de novo, no contexto da pergunta
mosquito
@gnat: O TO também diz que não sabe sobre as origens das exceções. Por isso, um pouco de pano de fundo por que as exceções estão por toda parte na terra OO parecia bom para mim. YMMV
AH
1
@ Ah, eu tenho que concordar com o mosquito, além da linha de abertura, ele realmente não aborda a questão. Sua resposta ao gnat foi "diz que ele não sabe sobre as origens das exceções", mas você realmente não forneceu uma origem de exceções, apenas algum uso aleatório de exceções durante a instanciação do objeto.
Gente, sério? -1? A maioria das outras respostas também não é 100% direta. +1 de mim para compensar. Esta resposta fornece bons conselhos de fundo em um mundo de projetos de classe quebrados. (Alteração: Menção multi-passo construtores deve ser evitado)
Jo Então,
44

É apenas OOP relacionado?

Não. Exceções e POO não estão relacionadas.

O tratamento de exceções é um mecanismo para lidar com erros. Uma exceção é tratada salvando o estado atual de execução em um local predefinido e alternando a execução para uma sub-rotina específica conhecida como manipulador de exceções.

Comparando C ( não é realmente a linguagem OOP , possível de alguma forma simular exceções em C ) e C ++ (OOP, suporta exceções), nada impede o comitê padrão de C de adicionar manipulação de exceções a C, ainda não fará de C uma linguagem OOP.

BЈовић
fonte
2
Você pode até argumentar que já existem algum tipo de exceção suportada no sistema operacional usual. Deixe seu programa travar (a "exceção" não capturada) e, com um dump principal e um depurador, você receberá um rastreamento de pilha.
bhaak
12
Até o MS BASIC do início dos anos 80 teve um tratamento de exceções:ON ERROR GOTO xxxx
jwernerny
1
@bhaak Ele também poderia estar falando sobre despejos de memória no Windows
johnl
11
@jwernerny Tratamento de erros? Certo. Mas ninguém chamaria isso de manipulação de exceção. De fato, era rotineiramente contrastado com o tratamento de exceção (estruturado).
Konrad Rudolph
1
@jwernerny não tenho certeza se eu sigo; tratamento de exceções, como eu entendi, é uma maneira muito específica de lidar com erros. Quando ouço uma exceção, sempre penso na try catchconstrução.
Andy
12

Uma exceção é, simplesmente, uma situação excepcional que requer atenção e, muitas vezes, uma mudança no fluxo da execução de um programa. Por essa definição, as exceções e o tratamento de exceções não se limitam à orientação a objetos, e erros simples de programa podem ser considerados uma forma de exceção.

As linguagens orientadas a objetos geralmente têm uma classe de exceção nativa e, dependendo do contexto, a palavra "exceção" pode realmente se referir a essa classe nativa em vez do conceito geral. O tratamento de exceções orientadas a objetos é, como a maioria da orientação a objetos, açúcar sintático e pode ser facilmente emulado em linguagens decisivamente não orientadas a objetos. Aqui está um exemplo de C, no wikibook de programação C :

#include <stdio.h>
#include <setjmp.h>

jmp_buf test1;

void tryjump()
{
    longjmp(test1, 3);
}

int main (void)
{
    if (setjmp(test1)==0) {
        printf ("setjmp() returned 0.");
        tryjump();
    } else {
        printf ("setjmp returned from a longjmp function call.");
    }
}
yannis
fonte
6
Não é apenas açúcar sintático. Recriar uma pilha completa de desenrolamento e manipuladores de captura baseados em tipo é difícil com o setjmp. Além disso, a compilação especial de exceções resulta em vantagens que não podem ser imitadas pelo setjmp.
EdA-qa mort-ora-y
3
Eu odeio as exceções de descrição são situações excepcionais. Prefiro dizer que exceções devem ser geradas (lançadas) quando uma situação de erro não pode ser resolvida com o contexto atual, porque não há informações suficientes no contexto atual para corrigir o erro corretamente.
Martin York
+1 para setjmp.h
mosquito
9

A resposta é um simples NÃO.

Um bom exemplo para um idioma não OO com exceções é o ADA.

Uwe Plonus
fonte
4
Hum, por que a ADA não é uma linguagem OO? É verdade que o ADA83 não possuía polimorfismo, mas ainda podia ser considerado baseado em objetos. Também desde o ADA95, a linguagem é totalmente orientada a objetos.
yannis
Até onde eu sei, o tratamento de exceções é mais antigo que o ADA83, portanto, o ADA em si é um não OO com tratamento de exceções.
precisa saber é o seguinte
2
@YannisRizos: O Ada83 possui pacotes e pacotes genéricos, mas não objetos. Eles foram introduzidos com o Ada95.
Mouviciel
2
@ Yannis - Objetos sem polimorfismo é como programação estruturada sem blocos aninhados. O polimorfismo é uma das características definidoras da POO. Mesmo no Ada95, os tipos que oferecem suporte à ligação em tempo de execução são chamados de "tipos marcados" em vez de "classes", embora, é claro, isso seja apenas ortografia. O Ada 83 tinha registros variantes e vários outros tipos, mas nenhum desses tipos fornece recursos específicos para OOP. O Ada 83 era modular e estruturado, mas não era orientado a objetos.
Steve314
3
@ Yannis - basicamente, algumas pessoas na comunidade Ada (como alguns advogados da maioria dos idiomas) não podem aceitar que um recurso possa ser bom, mas não implementado em seu idioma favorito, e criarão todo tipo de desculpa para acreditar no contrário. No entanto, nem mesmo uma boa linguagem precisa ter todos os recursos possíveis de boa linguagem (embora seja fácil acreditar que os designers da Ada pensaram assim). Eu realmente não acredito na abordagem minimalista do design de idiomas, mas os idiomas maximalistas também não são perfeitos.
Steve314
7

Algumas respostas muito boas aqui já. Outros exemplos para linguagens de programação não OOP, com exceções:

  • Oracle PL / SQL

  • Visual Basic clássico (V6 e abaixo, "On Error Goto" é IMHO uma forma de tratamento de exceções)

(Para ser sutil: você encontra alguns elementos OO em ambas as linguagens, mas a mecânica de manipulação de exceções não as utiliza, acho que porque o conceito foi introduzido anos antes de os elementos OO serem adicionados a essas linguagens).

Doc Brown
fonte
Pelo menos as versões posteriores do QuickBASIC no DOS (que antecederam o Visual Basic; o QB 4.5 era 1988, de acordo com a Wikipedia, VB 1.0 1991), tinham tratamento de erros usando a ON ERROR GOTOsintaxe. Até o QuickBASIC tinha alguns conceitos semelhantes ao OO (acho que o QB 4.5 até suportava classes de algum tipo), mas seria difícil chamar o BASIC, na maioria das vezes tradicional, de uma linguagem orientada a objetos adequada. [Wikipedia ]
um CVn em
5

A idéia básica por trás das exceções é limpar o fluxo do programa para que um programador possa seguir o caminho de execução "normal" mais facilmente. Considere um caso simples de abrir um arquivo em C. Imediatamente após tentar abrir o arquivo, o programador precisa examinar a resposta da chamada fopen () e decidir se a chamada foi bem-sucedida. Se a chamada não for bem-sucedida, o programador deverá responder adequadamente. A próxima chamada no caminho de execução "normal", talvez uma chamada para fread () ou fwrite (), apareça após o tratamento das condições de erro ou falha. Isso pode estar na próxima tela.

Com um idioma que fornece exceções, a chamada fopen () equivalente pode ser seguida imediatamente pelo fread () ou fwrite (). Não há tratamento de erros que oculte a "próxima etapa" do caminho de execução "normal". O programador pode ver mais do caminho normal em uma única tela e também pode seguir a execução mais facilmente. O tratamento de erros é movido para outra parte do programa.

Exceções em si não são um conceito de POO, mas geralmente são implementadas usando conceitos de POO que os tornam mais convenientes e poderosos. Por exemplo, as exceções podem ser definidas com uma hierarquia de herança. Usando o nosso exemplo de abertura e leitura ou gravação de um arquivo, cada uma dessas chamadas pode gerar uma variedade de exceções - FileClosedException, DeviceFullException, NoSuchFileException, InsufficientFilePermissionsException etc. Cada uma delas pode herdar de FileException, que pode herdar de IOException, que pode herdar de GenericException.

Se o programador estiver executando uma implementação rápida e suja para testar um conceito, ele poderá ignorar o tratamento de exceções e apenas implementar um único manipulador para GenericException. Esse manipulador manipulará uma GenericException e qualquer exceção que herda de GenericException. Se ele deseja tratar qualquer exceção relacionada a arquivo da mesma maneira, ele pode escrever um manipulador para FileException. Isso será chamado para FileExceptions e quaisquer exceções herdadas de FileException. Se ele quiser escrever um programa que responderá diferentemente a uma variedade de condições de erro, ele poderá escrever um manipulador específico para cada exceção específica.

MikeD
fonte
3

Outros responderam "Não" com exemplos de idiomas. Eu pensei que poderia estender adicionando um exemplo de como adicionar exceções a um idioma sem nunca envolver OOP.

Farei isso no caso da DSKL (Declarative Sequential Kernel Language) da OZ , uma linguagem bem adequada para assuntos acadêmicos como este. O DSKL (ou DKL) pode ser visto aqui (resultado da pesquisa aleatória), a parte Declarações e Valores. A definição exata não é importante, além de ser uma linguagem muito simples, sem variáveis ​​modificáveis ​​(elas são declaradas e posteriormente vinculadas) e nenhuma OOP incorporada.

OOP não pode nem ser adicionado como uma abstração linguística a essa linguagem do kernel. Adicionando nomes exclusivos ao idioma do kernel (NewName) e usando o escopo local, o encapsulamento pode ser alcançado. Ou adicionando um estado mutável à linguagem do kernel (NewCell) e usando o escopo local OOP adequado com encapsulamento pode ser alcançado. Mas não pode ser alcançado apenas com a linguagem do kernel especificada.

Se adicionarmos exceções ao idioma do kernel, teremos um idioma sem suporte a OOP, mas teremos exceções. Deixe-me mostrar como:

Definindo uma máquina abstrata com uma pilha e um armazenamento, podemos definir o que cada declaração em nossa linguagem deve fazer (a semântica da declaração). Por exemplo, skipna pilha não deve fazer nada, A = 3na pilha deve vincular (/ unificar) A a (/ com) 3.

Começamos adicionando a sintaxe de como nossas exceções devem ser definidas. Fazemos isso adicionando mais duas cláusulas à <statement>DKL.

<statement>  ::== ... (old stuff)
                 | try <statement> catch <id> then <statement> end
                 | raise <id> end

Aqui está o try / catch conhecido e uma maneira de gerar / lançar exceções.

Definimos suas semânticas pela maneira como elas devem funcionar na máquina abstrata:

Tente
A declaração semântica é: (try <statement1> catch <id> then <statement2> end)
Faça:

  1. Empurre para a pilha a instrução semântica (catch <id> then <statement2> end)
  2. Empurre para a pilha a instrução semântica (<statement1>)

Observe que a instrução 1 estará no topo da pilha e tentada executada primeiro.

Aumentar
A declaração semântica é (raise <id> end)
:

  1. Se nada mais estiver na pilha, pare e relate uma exceção não capturada.
  2. Senão, pop a primeira declaração semântica da pilha. Se não for uma declaração de captura, vá para a etapa 1.
  3. Temos uma pegadinha, no formulário (catch <id> then <statement> end)
    Empurre (<statement>)para a pilha.

Catch
Se virmos uma instrução catch durante a execução normal, isso significa que tudo o que havia dentro foi executado sem gerar exceções até esse nível. Assim, apenas colocamos catcha pilha e não fazemos nada.

QED, temos um idioma com exceções e sem possibilidade de POO.

Eu removi a parte do ambiente da máquina abstrata para simplificá-la.

Matsemann
fonte
1

Não.

IIRC, exceções apareceram antes dos primeiros idiomas OO. AFAIK, as exceções foram primeiro suportadas pelas implementações iniciais do LISP. Os idiomas estruturados iniciais (por exemplo, ALGOL) e os idiomas OO iniciais (por exemplo, SIMULA) não suportavam exceções.

Kevin Cline
fonte
O ALGON 68, é claro, tinha exceções ("eventos"), mas tinha todo o resto também. O PL / I também os possuía ("condições ON"), e há literatura de 1969 descrevendo seu uso.
precisa saber é o seguinte