Apakah pengecualian merupakan konsep OOP?

37

Setelah membaca posting kemarin, saya menyadari saya tidak tahu banyak tentang asal-usul pengecualian. Apakah ini hanya konsep terkait OOP? Saya cenderung berpikir begitu, tapi sekali lagi ada pengecualian basis data.

John V
sumber
Saya pernah membaca bahwa "Tuan Goodenuf" (atau serupa) menemukan pengecualian sebagai tanggapan "tidak apa-apa, ini Goodenuf, eh!" penindasan gaya. Sepertinya saya tidak dapat menemukan referensi sekarang - mungkin orang lain bisa. Akan menarik untuk mengetahui bahasa apa yang mereka tambahkan pertama.
Steve314
7
Haskell memiliki pengecualian dan sama sekali bukan OOP
Daniel Gratzer
1
Meskipun pengecualian itu sendiri tidak sepenuhnya berorientasi objek, praktik umum mendefinisikan pengecualian sebagai objek dan melempar dan menangkap contoh objek ini jelas sangat OOP.
Dougvj
Apa perbedaan antara pengecualian dan GOTO akan menjadi pertanyaan yang menarik.
Austin Henley
2
@Austin - bagaimana dengan "walaupun melempar pengecualian melanggar prinsip titik keluar tunggal bahwa beberapa murid paling ketat dari pendukung pemrograman terstruktur sebagai mutlak, mereka tidak mengizinkan aliran kontrol spageti yang tidak dibatasi dengan cara yang gotobenar. Secara khusus, target dari lemparan ditentukan oleh konteks, berdasarkan pada bersarangnya struktur blok. Dengan demikian, pengecualian bahkan tergantung pada bentuk pemrograman terstruktur yang sedikit kurang ketat di mana prinsip jalan keluar tunggal diambil sebagai pedoman, tetapi bukan mutlak ".
Steve314

Jawaban:

5

Pengecualian bukan konsep OOP.

Tetapi mereka tidak sepenuhnya tidak berhubungan baik dalam satu titik kecil kecil.

Seperti yang ditunjukkan oleh jawaban lain: Konsep pengecualian telah membuatnya dalam beberapa bahasa non-OOP. Tidak ada dalam konsep itu yang membutuhkan sesuatu dari OOP.

Tetapi apa pun jika tidak semua bahasa OOP yang menganggap serius OOP memerlukan pengecualian karena metode penanganan kesalahan lainnya gagal pada satu titik tertentu: Konstruktor.

Salah satu poin dari OOP adalah bahwa suatu objek harus merangkum dan mengelola keadaan internalnya secara lengkap dan konsisten. Ini juga berarti bahwa dalam OOP murni, Anda memerlukan konsep untuk membuat objek baru dengan status konsisten "secara atomis" - mulai dari alokasi memori (jika diperlukan) hingga inisialisasi ke keadaan bermakna (mis., Hanya memusatkan memori tidak cukup) harus dilakukan dalam satu ekspresi. Oleh karena itu seorang konstruktor diperlukan:

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

Tetapi ini berarti bahwa konstruktor juga dapat gagal karena beberapa kesalahan. Bagaimana menyebarkan informasi kesalahan keluar dari konstruktor tanpa pengecualian?

  • Nilai pengembalian? Gagal karena dalam beberapa bahasa newhanya dapat mengembalikan nulltetapi tidak ada informasi yang bermakna. Dalam bahasa lain (mis. C ++) myFoobukan pointer. Anda tidak dapat memeriksanya null. Anda juga tidak dapat bertanya myFootentang kesalahan - itu tidak diinisialisasi dan karena itu "tidak ada" dalam pemikiran OOP.

  • Bendera kesalahan global? Begitu banyak tentang negara enkapsulasi dan kemudian beberapa variabel global? Pergi ke h ... ;-)

  • Campuran? Tidak mungkin lebih baik.

  • ?

Jadi pengecualian adalah konsep yang lebih mendasar daripada OOP tetapi OOP dibangun di atas mereka secara alami.

AH
sumber
3
sejauh yang saya tahu, satu-satunya kata dalam "jawaban" ini yang menjawab pertanyaan aktual yang diajukan adalah "tidak". Sisanya tampaknya tentang pengecualian dalam OOP - dengan segala hormat kepada saya ini berbunyi di suatu tempat antara samar-samar terkait dan sama sekali tidak relevan - lagi, dalam konteks pertanyaan yang diajukan
nyamuk
@gnat: TO juga mengatakan dia tidak tahu tentang asal-usul pengecualian. Oleh karena itu sedikit latar belakang mengapa pengecualian ada di mana-mana di tanah OO tampaknya baik-baik saja bagi saya. YMMV
AH
1
@ Aku harus setuju dengan nyamuk, selain dari kalimat pembukaan, itu benar-benar tidak menjawab pertanyaan. Respons Anda terhadap agas adalah "mengatakan dia tidak tahu tentang asal-usul pengecualian" namun Anda tidak benar-benar memberikan asal pengecualian, hanya beberapa penggunaan pengecualian acak selama instantiasi objek.
Kawan, serius? -1? Sebagian besar jawaban lain tidak 100% to the point, baik. +1 dari saya untuk kompensasi. Jawaban ini memberikan saran latar belakang yang baik dalam dunia desain kelas yang rusak. (Amandemen: Sebutkan konstruktor multi-langkah harus dihindari)
Jo So
44

Apakah hanya terkait OOP?

Tidak. Pengecualian dan OOP tidak terkait.

Penanganan pengecualian adalah mekanisme untuk menangani kesalahan. Pengecualian ditangani dengan menyimpan kondisi eksekusi saat ini di tempat yang telah ditentukan dan mengalihkan eksekusi ke subrutin tertentu yang dikenal sebagai penangan pengecualian.

Membandingkan C ( tidak benar-benar bahasa OOP , mungkin untuk meniru bagaimana pun juga pengecualian dalam C ) dan C ++ (OOP, mendukung pengecualian), tidak ada yang mencegah komite standar C menambahkan pengecualian penanganan ke C, itu masih tidak akan menjadikan C sebagai bahasa OOP.

BЈовић
sumber
2
Anda bahkan dapat berdebat bahwa sudah ada semacam pengecualian yang didukung di OS yang biasa. Biarkan program Anda macet ("pengecualian" yang tidak tertangkap) dan dengan dump inti dan debugger, Anda bahkan mendapatkan jejak stack.
bhaak
12
Bahkan MS BASIC dari awal 80-an memiliki penanganan perkecualian:ON ERROR GOTO xxxx
jwernerny
1
@haak Dia juga bisa berbicara tentang Memory dumps di Windows
JohnL
11
@jwernerny Menangani kesalahan? Yakin. Tapi tidak ada yang akan menyebut penanganan pengecualian itu. Bahkan, itu secara rutin kontras dengan penanganan pengecualian (terstruktur).
Konrad Rudolph
1
@ jwernerny tidak yakin saya mengikuti; penanganan pengecualian seperti yang saya mengerti itu adalah cara yang sangat spesifik untuk melakukan penanganan kesalahan. Ketika saya mendengar pengecualian, saya selalu memikirkan try catchkonstruknya.
Andy
12

Pengecualiannya adalah, sederhananya, situasi luar biasa yang membutuhkan perhatian dan seringkali perubahan dalam alur pelaksanaan program. Menurut definisi itu, pengecualian dan penanganan pengecualian tidak terbatas pada orientasi objek, dan kesalahan program sederhana dapat dianggap sebagai bentuk pengecualian.

Bahasa berorientasi objek biasanya memiliki kelas pengecualian asli, dan tergantung pada konteksnya kata "pengecualian" mungkin memang merujuk ke kelas asli itu alih-alih konsep umum. Penanganan pengecualian berorientasi objek, karena sebagian besar orientasi objek, gula sintaksis, dan dapat dengan mudah ditiru dalam bahasa yang tidak berorientasi objek. Berikut adalah contoh C, dari wikibook Pemrograman 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
sumber
6
Ini bukan hanya gula sintaksis. Menciptakan stack handler yang penuh dengan gulungan dan penangan berbasis tipe sulit dilakukan dengan setjmp. Selain itu, kompilasi khusus pengecualian menghasilkan keuntungan yang tidak dapat ditiru oleh setjmp.
edA-qa mort-ora-y
3
Saya benci deskripsi pengecualian adalah situasi luar biasa. Saya lebih suka mengatakan pengecualian harus dihasilkan (dilempar) ketika situasi kesalahan tidak dapat diselesaikan dengan konteks saat ini karena tidak ada cukup informasi dalam konteks saat ini untuk memperbaiki kesalahan dengan benar.
Martin York
+1 untuk setjmp.h
nyamuk
9

Jawabannya adalah TIDAK sederhana.

Contoh yang baik untuk bahasa non-OO dengan pengecualian adalah ADA.

Uwe Plonus
sumber
4
Hm, mengapa ADA bukan bahasa OO? Memang, ADA83 tidak memiliki polimorfisme tetapi masih bisa dianggap berbasis objek. Juga sejak ADA95 bahasa sepenuhnya berorientasi objek.
yannis
Sejauh yang saya tahu penanganan pengecualian lebih tua dari ADA83 oleh karena itu ADA itu sendiri adalah non-OO dengan penanganan pengecualian.
Uwe Plonus
2
@YannisRizos: Ada83 memiliki paket dan paket generik tetapi tidak objek. Mereka diperkenalkan dengan Ada95.
mouviciel
2
@Yannis - Objek tanpa polimorfisme seperti pemrograman terstruktur tanpa blok bersarang. Polimorfisme adalah salah satu ciri utama OOP. Bahkan di Ada95, tipe yang mendukung pengikatan run-time disebut "tipe tag" daripada "kelas", meskipun tentu saja itu hanya pengejaan. Ada 83 memiliki catatan varian dan berbagai jenis lainnya, tetapi tidak satu pun dari jenis itu menyediakan fitur yang khusus untuk OOP. Ada 83 adalah modular dan terstruktur, tetapi tidak berorientasi objek.
Steve314
3
@Yannis - pada dasarnya, beberapa orang di komunitas Ada (seperti beberapa pendukung sebagian besar bahasa) tidak dapat menerima bahwa fitur dapat menjadi baik, namun tidak diterapkan dalam bahasa favorit mereka, dan akan membuat segala macam alasan untuk meyakini sebaliknya. Namun itu bahkan tidak seolah-olah bahasa yang baik perlu memiliki semua fitur bahasa yang mungkin baik (meskipun mudah untuk percaya bahwa para desainer Ada berpikir begitu). Saya sebenarnya bukan orang yang percaya pada pendekatan minimalis untuk desain bahasa, tetapi bahasa maksimal juga tidak sempurna.
Steve314
7

Beberapa jawaban yang sangat bagus sudah ada di sini. Contoh lain untuk bahasa pemrograman non-OOP yang memiliki pengecualian:

  • Oracle PL / SQL

  • klasik Visual Basic (V6 dan di bawah, "On Error Goto" adalah IMHO bentuk penanganan pengecualian)

(Untuk menjadi seluk beluk: Anda menemukan beberapa elemen OO di kedua bahasa, tetapi mekanisme penanganan pengecualian tidak memanfaatkannya, saya kira karena konsepnya diperkenalkan bertahun-tahun sebelum elemen OO ditambahkan ke bahasa-bahasa tersebut).

Doc Brown
sumber
Setidaknya versi QuickBASIC kemudian pada DOS (yang mendahului Visual Basic; QB 4.5 adalah 1988 menurut Wikipedia, VB 1.0 1991) memiliki penanganan kesalahan menggunakan ON ERROR GOTOsintaks. Bahkan QuickBASIC memiliki beberapa konsep mirip OO (saya pikir QB 4.5 bahkan mendukung beberapa jenis), tetapi Anda akan sulit sekali menyebut sebagian besar BASIC tradisional sebagai bahasa berorientasi objek yang tepat. [Wikipedia ]
CVn
5

Ide dasar di balik pengecualian adalah untuk membersihkan aliran program sehingga programmer dapat mengikuti jalur eksekusi "normal" dengan lebih mudah. Pertimbangkan kasus sederhana membuka file dalam C. Segera setelah mencoba membuka file, programmer perlu memeriksa respons dari panggilan fopen () dan memutuskan apakah panggilan berhasil. Jika panggilan tidak berhasil, maka programmer harus merespons dengan tepat. Panggilan berikutnya di jalur eksekusi "normal", mungkin panggilan untuk menakut-nakuti () atau fwrite (), akan muncul setelah kondisi kesalahan atau kegagalan telah ditangani. Itu mungkin ada di layar berikutnya.

Dengan bahasa yang memberikan pengecualian, panggilan fopen () yang setara dapat segera diikuti oleh fread () atau fwrite (). Tidak ada penanganan kesalahan yang menyembunyikan "langkah selanjutnya" dari jalur eksekusi "normal". Programmer dapat melihat lebih banyak jalur normal pada satu layar, sehingga dapat mengikuti eksekusi dengan lebih mudah. Penanganan kesalahan dipindahkan ke bagian lain dari program.

Pengecualian itu sendiri bukanlah konsep OOP, tetapi mereka sering diimplementasikan menggunakan konsep OOP yang membuatnya lebih nyaman dan kuat. Misalnya, pengecualian dapat didefinisikan dengan hierarki warisan. Menggunakan contoh nosional kami membuka dan membaca atau menulis file, masing-masing panggilan tersebut dapat menghasilkan berbagai pengecualian - FileClosedException, DeviceFullException, NoSuchFileException, InsufficientFilePermissionsException, dll Masing-masing dapat mewarisi dari FileException, yang mungkin mewarisi dari IOException, yang mungkin mewarisi dari GenericException.

Jika programmer melakukan implementasi cepat dan kotor untuk menguji suatu konsep, ia mungkin mengabaikan penanganan pengecualian dan hanya mengimplementasikan handler tunggal untuk GenericException. Pawang itu akan menangani GenericException dan pengecualian apa pun yang mewarisi dari GenericException. Jika ia ingin memperlakukan pengecualian terkait file apa pun dengan cara yang sama, ia dapat menulis penangan untuk FileException. Itu akan dipanggil untuk FileExceptions dan pengecualian apa pun yang mewarisi dari FileException. Jika dia ingin menulis sebuah program yang akan merespons secara berbeda terhadap berbagai kondisi kesalahan, dia dapat menulis penangan khusus untuk setiap pengecualian tertentu.

MikeD
sumber
3

Yang lain menjawab dengan benar "Tidak" dengan contoh bahasa. Saya pikir saya dapat memperluas dengan menambahkan contoh tentang cara menambahkan pengecualian ke bahasa tanpa melibatkan OOP.

Saya akan melakukan ini dalam hal DSKL (Declarative Sequential Kernel Language) dari OZ , bahasa yang cocok untuk hal-hal akademis seperti ini. DSKL (atau DKL) dapat dilihat di sini (hasil pencarian acak), bagian Pernyataan dan Nilai. Definisi yang tepat tidak penting, selain ini menjadi bahasa yang sangat sederhana tanpa variabel yang dapat dimodifikasi (mereka dideklarasikan dan kemudian diikat), dan tidak ada OOP bawaan.

OOP bahkan tidak dapat ditambahkan sebagai abstraksi linguistik ke bahasa kernel ini. Dengan menambahkan nama unik ke bahasa kernel (NewName) dan menggunakan pelingkupan lokal, enkapsulasi dapat dicapai. Atau dengan menambahkan status yang dapat diubah ke bahasa kernel (NewCell) dan menggunakan cakupan lokal OOP yang tepat dengan enkapsulasi dapat dicapai. Tetapi tidak bisa dapat dicapai dengan bahasa kernel yang ditentukan saja.

Jika kemudian kita menambahkan pengecualian ke bahasa kernel kita akan memiliki bahasa tanpa dukungan OOP tetapi memiliki pengecualian. Biarkan saya tunjukkan caranya:

Mendefinisikan mesin abstrak dengan tumpukan dan penyimpanan, kita dapat mendefinisikan apa yang harus dilakukan oleh setiap pernyataan dalam bahasa kita ( semantik pernyataan itu). Misalnya skipdalam stack tidak melakukan apa-apa, A = 3dalam stack harus mengikat (/ menyatukan) A ke (/ dengan) 3.

Kita mulai dengan menambahkan sintaks tentang bagaimana pengecualian kita harus didefinisikan. Kami melakukan ini dengan menambahkan dua klausa lain ke <statement>dalam DKL.

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

Berikut ini adalah try / catch yang dikenal, dan cara untuk menaikkan / melempar pengecualian.

Kami mendefinisikan semantik mereka dengan bagaimana mereka harus bekerja pada mesin abstrak:

Coba
Pernyataan semantiknya adalah: (try <statement1> catch <id> then <statement2> end)
Lakukan:

  1. Dorong ke tumpukan pernyataan semantik (catch <id> then <statement2> end)
  2. Dorong ke tumpukan pernyataan semantik (<statement1>)

Perhatikan bahwa pernyataan 1 akan berada di atas tumpukan, dan coba dieksekusi terlebih dahulu.

Naikkan
Pernyataan semantik adalah: (raise <id> end)
Lakukan:

  1. Jika tidak ada lagi yang ada di tumpukan, hentikan dan laporkan pengecualian yang tidak tertangkap.
  2. Lain, pop pernyataan semantik pertama dari tumpukan. Jika itu bukan pernyataan penangkapan, lanjutkan ke langkah 1.
  3. Kami mendapatkan tangkapan, pada formulir (catch <id> then <statement> end)
    Push (<statement>)ke tumpukan.

Tangkapan
Jika kita melihat pernyataan tangkap selama eksekusi normal, ini berarti bahwa apa pun yang ada di dalam dieksekusi tanpa menaikkan pengecualian hingga tingkat ini. Jadi kita hanya membuang catchtumpukan dan tidak melakukan apa pun.

QED, kami memiliki bahasa dengan pengecualian dan tidak ada kemungkinan OOP.

Saya telah menghapus bagian lingkungan dari mesin abstrak untuk membuatnya lebih sederhana.

Matsemann
sumber
1

Tidak.

IIRC, pengecualian muncul sebelum bahasa OO pertama. AFAIK, pengecualian pertama kali didukung oleh implementasi LISP awal. Bahasa terstruktur awal (misalnya ALGOL) dan bahasa OO awal (mis. SIMULA) tidak mendukung pengecualian.

kevin cline
sumber
ALGON 68, tentu saja, memiliki pengecualian ("peristiwa"), tetapi semuanya memiliki yang lain juga. PL / Saya punya mereka ("ON kondisi") juga, dan ada literatur dari tahun 1969 menggambarkan penggunaannya.
Ross Patterson