Having read a post yesterday, I realized I did not know much about the origin of exceptions. Is it an OOP related concept only? I tend to think it is, but again there are database exceptions.
9
Exceptions are not an OOP concept.
But they are not completely unrelated either in one little tiny point.
As other answers have shown: The concept of exceptions has made it in several non-OOP languages. Nothing in that concept requires something from OOP.
But any if not all OOP languages which takes OOP seriously require exceptions because the other methods of error-handling fail at one specific point: The constructor.
One of the points of OOP is that an object shall encapsulate and manage its internal state completely and consistently. This also means that in pure OOP you need a concept to create a new object with a conistent state “atomically” – everything from memory allocation (if required) to the initialisation to a meaningful state (i.e. simple zeroing the memory is not enough) must be done in one expression. Hence a constructor is required:
Foo myFoo = Foo("foo", "bar", 42);
But this means that the constructor can also fail due to some error. How to propagate the error information out from the constructor without exceptions?
-
Return value? Fails since in some languages
new
could return onlynull
but not any meaningfull information. In other languages (e.g. C++)myFoo
is not a pointer. You could not check it againstnull
. Also you cannot askmyFoo
about the error – it is not initialized and therefore “does not exist” in OOP thinking. -
Global error flag? So much about encapsulating state and then some global variable? Go to h… 😉
-
A mixture? In no way better.
-
?
So exceptions are a more fundamental concept than OOP but OOP builds upon them in a natural way.
4
Is it OOP related only?
No. Exceptions and OOP are unrelated.
Exceptions handling is a mechanism to handle errors. An exception is handled by saving the current state of execution in a predefined place and switching the execution to a specific subroutine known as an exception handler.
Comparing C (not really OOP language, possible to somehow emulate exceptions in C) and C++ (OOP, supports exceptions), nothing prevents C’s standard committee from adding exceptions handling to C, it will still not make C an OOP language.
9
An exception is, simply put, an exceptional situation requiring attention and often a change in the flow of a program’s execution. By that definition, exceptions and exception handling are not limited to object orientation, and simple program errors can be considered a form of exception.
Object oriented languages typically have a native exception class, and depending on context the word “exception” might indeed refer to that native class instead of the general concept. Object oriented exception handling is, as most of object orientation, syntactic sugar, and can be easily emulated in decisively non object oriented languages. Here’s a C example, from the C Programming wikibook:
#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.");
}
}
3
The answer is a simple NO.
A good example for a non-OO language with exceptions is ADA.
10
Some very good answers here already. Other examples for non-OOP programming languages having exceptions:
-
Oracle PL/SQL
-
classic Visual Basic (V6 and below, “On Error Goto” is IMHO a form of exception handling)
(To be nitty: you find some OO elements in both of the languages, but the exception handling mechanics does not make use of them, I guess because the concept was introduced years before the OO elements were added to those languages).
1
The basic idea behind exceptions is to clean up program flow so that a programmer can follow the “normal” execution path more easily. Consider a simple case of opening a file in C. Immediately after attempting to open the file, the programmer needs to examine the response from the fopen() call and decide if the call succeeded. If the call did not succeed, then the programmer must respond appropriately. The next call in the “normal” execution path, perhaps a call to fread() or fwrite(), would appear after the error or failure conditions have been handled. That may be on the next screen.
With a language that provides exceptions, the equivalent fopen() call can be followed immediately by the fread() or fwrite(). There is no error handling that is hiding the “next step” of the “normal” execution path. The programmer can see more of the normal path on a single screen, and so can follow the execution more easily. The error handling is moved to another part of the program.
Exceptions themselves are not an OOP concept, but they are often implemented using OOP concepts which make them more convenient and powerful. For instance, exceptions may be defined with an inheritance hierarchy. Using our notional example of opening and reading or writing a file, each of those calls may generate a variety of exceptions – FileClosedException, DeviceFullException, NoSuchFileException, InsufficientFilePermissionsException, etc. Each of those may inherit from FileException, which may inherit from IOException, which may inherit from GenericException.
If the programmer is doing a quick and dirty implementation to test a concept, he might mostly ignore exception handling and just implement a single handler for GenericException. That handler will handle a GenericException and any exception which inherits from GenericException. If he wants to treat any file related exception the same way, he can write a handler for FileException. That will be called for FileExceptions and any exceptions that inherit from FileException. If he wants to write a program that will respond differently to a variety of error conditions, he can write a specific handler for each specific exception.
Others have rightly answered “No” with examples of languages. I thought I could extend by adding an example on how to add exceptions to a language without ever involving OOP.
I will do this in case of the DSKL (Declarative Sequential Kernel Language) of OZ, a language well suited for academia stuff like this. The DSKL (or DKL) can be seen here (random search result), the Statements and Values part. The exact definition is not important, other than this being a very simple language with no modifiable variables (they are declared and later bound), and no OOP built in.
OOP can not even be added as an linguistic abstraction to this kernel language. By adding unique names to the kernel language (NewName) and using local scoping, encapsulation can be achieved. Or by adding a mutable state to the kernel language (NewCell) and using local scoping proper OOP with encapsulation can be achieved. But it can not be achieved with the specified kernel language alone.
If we then add exceptions to the kernel language we will have a language with no OOP-support but have exceptions. Let me show how:
Defining an abstract machine with a stack and a storage, we can define what each statement in our language should do (the semantics of the statement). For instance skip
in the stack should do nothing, A = 3
in the stack should bind(/unify) A to(/with) 3.
We start by adding the syntax of how our exceptions should be defined. We do this by adding another two clauses to the <statement>
in the DKL.
<statement> ::== ... (old stuff)
| try <statement> catch <id> then <statement> end
| raise <id> end
Here is the known try/catch, and a way to raise/throw exceptions.
We define their semantics by how they should work on the abstract machine:
Try
The semantic statement is: (try <statement1> catch <id> then <statement2> end)
Do:
- Push onto the stack the semantic statement
(catch <id> then <statement2> end)
- Push onto the stack the semantic statement
(<statement1>)
Note that statement 1 will be on top of the stack, and tried executed first.
Raise
The semantic statement is: (raise <id> end)
Do:
- If nothing more is on the stack, stop and report an uncaught exception.
- Else, pop the first semantic statement from the stack. If it’s not a catch statement, go to step 1.
- We’ve gotten a catch, on the form
(catch <id> then <statement> end)
Push(<statement>)
onto the stack.
Catch
If we see a catch-statement during normal execution, this means that whatever was inside executed without raising exceptions up to this level. Thus we just pop the catch
of the stack and do nothing.
QED, we have a language with exceptions and no possibility of OOP.
I’ve removed the environment part from the abstract machine to make it simpler.
No.
IIRC, exceptions appeared before the first OO languages. AFAIK, exceptions were first supported by early LISP implementations. Early structured languages (e.g. ALGOL) and early OO languages (e.g. SIMULA) did not support exceptions.
1