Pemrograman Berorientasi Objek (OOP) adalah paradigma pemrograman yang populer dan tangguh, yang digunakan untuk mengorganisir dan mengelola kode program. Salah satu konsep utama dalam OOP adalah abstraksi. Abstraksi memungkinkan pengembang program untuk mengisolasi dan menyembunyikan detail implementasi behavior atau method dari suatu class, dan memfokuskan pada fitur penting yang relevan. Adapun detil implementasi behavior tersebut akan didefinisikan pada subclassnya. Keuntungan dari abstraksi juga dapat dimanfaatkan sebagai guideline dalam mengembangkan sebuah class yang merupakan turunan sebuah class abstrak.
Python, sebagai salah satu bahasa yang mendukung OOP tentunya juga memiliki fitur untuk bisa menerapkan abstraksi. Bagaimana cara menerapkan abstraksi di Python? Serta bagaimana contohnya? Ini yang akan dibahas di artikel ini.
Perlu diketahui bahwa sebuah class dapat memiliki method yang abstrak maupun non-abstrak. Sebuah class yang memiliki minimal satu method abstrak, selanjutnya disebut class abstrak. Method abstrak adalah method yang tidak memiliki implementasi atau body. Pada class abstrak, kita tidak bisa melakukan instansiasi atau membuat obyek darinya.
Apa Perlunya Penggunaan Class Abstrak?
Untuk melihat perlunya penggunaan class abstrak, saya berikan contoh sederhana berikut ini.
class Lingkaran:
def __init__(self, jejari):
self.jejari = jejari
def luas(self):
return 3.14 * self.jejari * self.jejari
class Persegi:
def __init__(self, sisi):
self.sisi = sisi
def luas(self):
return self.sisi * self.sisi
class Segitiga:
def __init__(self, alas, tinggi):
self.alas = alas
self.tinggi = tinggi
def luas(self):
return 0.5 * self.alas * self.tinggi
bangunDatar = [
Lingkaran(5),
Persegi(4),
Segitiga(6, 3)
]
for bangun in bangunDatar:
print(f"Luasnya: {bangun.luas()}")
Struktur kode program di atas memiliki beberapa kelemahan.
Pertama adalah tidak ada kontrak struktur yang jelas terhadap setiap class. Dalam hal ini tidak ada kepastian bahwa semua class akan memiliki method luas() karena setiap class dibuat secara independen. Jika developer lain menambahkan class baru (misalnya Persegipanjang) dan lupa mendefinisikan luas(), maka akan muncul error runtime saat dipanggil.
Kedua adalah tidak adanya struktur class yang konsisten. Tidak ada jaminan bahwa semua class akan memiliki nama method dan struktur yang seragam. Jika satu class menggunakan hitung_luas() sementara class lain menggunakan luas(), maka akan sulit untuk mengelola kode program secara umum.
Masalah di atas dapat tertangani dengan menerapan konsep class abstrak, yang dengannya dapat digunakan sebagai jaminan kontrak dan kekonsistenan dalam membuat class-class yang memiliki karakteristik yang sama.
Library Abstract Base Classes (ABC)
Untuk menerapkan abstraksi di Python, kita membutuhkan library bernama Abstract Base Classes (ABC). Library ini secara default sudah ada di dalam modul utama Python, sehingga kita tidak perlu menginstalnya secara manual.
Library ABC digunakan untuk mendefinisikan sebuah class abstrak. Berikut ini adalah cara membuat class abstrak dengan library ABC tersebut.
from abc import ABC, abstractmethod
class MyClass(ABC):
@abstractmethod
def myMethod1(self):
pass
def myMethod2(self):
print("Hello World")
Contoh di atas menggambarkan cara membuat sebuah class abstrak bernama MyClass yang memiliki sebuah method abstrak myMethod1(). Method ini tidak memiliki body, ditandai tidak adanya implementasi di dalamnya. Adapun myMethod2() adalah method yang tidak abstrak.
Apabila kita mencoba membuat obyek dari MyClass, misalnya obyek c
c = MyClass()
maka akan muncul error yang menunjukkan bahwa sebuah obyek tidak bisa diinstansiasi dari class MyClass yang abstrak.
TypeError: Can't instantiate abstract class MyClass with abstract methods myMethod1
Implementasi Method Abstrak
Jika sebuah class abstrak sudah didefinisikan, maka selanjutnya kita bisa membuat sebuah subclass yang nantinya memiliki implementasi method abstrak tersebut. Perhatikan contoh berikut ini.
from abc import ABC, abstractmethod
# class abstrak
class MyClass(ABC):
@abstractmethod
def myMethod1(self):
pass
def myMethod2(self):
print("Hello World")
# subclass dari MyClass
class MySubClass(MyClass):
# implementasi dari myMethod1()
def myMethod1(self):
print("Hello Python")
Contoh program di atas menunjukkan telah dibuat class MySubClass yang merupakan subclass dari MyClass. Di dalam MySubClass dibuat myMethod1() yang menjelaskan detil dari implementasi myMethod1() yang masih abstrak dari superclassnya (MyClass), yaitu mencetak “Hello Python”.
Sehingga apabila kita buat sebuah obyek dari MySubClass, kemudian memanggil method myMethod1() dan myMethod2() maka akan tampil sebagai berikut:
c = MySubClass()
c.myMethod1() # menampilkan "Hello World"
c.myMethod2() # menampilkan "Hello Python"
Catatan penting yang perlu kita perhatikan adalah, bahwa sebuah subclass dari superclass yang abstrak, wajib mengimplementasikan semua method yang masih abstrak warisan dari superclassnya. Jika tidak, maka subclass itupun nantinya juga bersifat abstrak, sehingga tidak bisa dilakukan instansiasi obyek terhadapnya. Perhatikan contoh berikut ini.
from abc import ABC, abstractmethod
# class abstrak
class MyClass(ABC):
@abstractmethod
def myMethod1(self):
pass
def myMethod2(self):
print("Hello World")
# subclass dari MyClass
class MySubClass(MyClass):
def myMethod3(self):
print("Hello Indonesia")
Pada contoh di atas, MySubClass adalah subclass dari MyClass (superclass). Namun, di dalamnya hanya terdapat method myMethod3() yang mencetak "Hello Indonesia". Sedangkan ia mewarisi method myMethod1() yang masih abstrak dari superclassnya. Disebabkan karena di dalam MySubClass belum ada implementasi dari myMethod1(), menyebabkan MySubClass menjadi class abstrak yang tidak bisa dibuat obyek darinya.
c = MySubClass()
akan muncul error
TypeError: Can't instantiate abstract class MySubClass with abstract methods myMethod1
Studi Kasus Abstraksi
Pada bagian ini akan diberikan sebuah studi kasus penerapan abstraksi di Python. Misalkan kita diminta membuat program Python untuk menghitung luas dan keliling bangun datar, yaitu: persegi panjang, dan lingkaran.
Penyelesaian dari kasus tersebut, dapat kita mulai dari membuat sebuah class BangunDatar. Di dalam bangun datar ini memiliki method hitungLuas() dan hitungKeliling(). Namun dalam hal ini kedua method belum perlu didefinisikan secara detil bagaimana menghitungnya, disebabkan formula yang berbeda-beda tiap bangun datarnya.
from abc import ABC, abstractmethod
class BangunDatar(ABC):
@abstractmethod
def hitungLuas(self):
pass
@abstractmethod
def hitungKeliling(self):
pass
Setelah class BangunDatar dibuat, selanjutnya kita buat subclassnya yaitu class untuk setiap jenis bangun datarnya, yaitu PersegiPanjang dan Lingkaran. Di dalam subclass inilah, nantinya formula perhitungan luas dan keliling akan didefinisikan.
from abc import ABC, abstractmethod
class BangunDatar(ABC):
@abstractmethod
def hitungLuas(self):
pass
@abstractmethod
def hitungKeliling(self):
pass
class PersegiPanjang(BangunDatar):
panjang = 0
lebar = 0
# implementasi hitungLuas()
def hitungLuas(self):
return self.panjang * self.lebar
# implementasi hitungKeliling()
def hitungKeliling(self):
return 2*(self.panjang + self.lebar)
class Lingkaran(BangunDatar):
jejari = 0
# implementasi hitungLuas()
def hitungLuas(self):
return 3.14 * self.jejari * self.jejari
# implementasi hitungKeliling()
def hitungKeliling(self):
return 2 * 3.14 * self.jejari
Perhatikan program di atas! Pada subclass PersegiPanjang dan Lingkaran, masing-masing sudah didefinisikan secara detil rumus perhitungan luas dan kelilingnya berdasarkan atribut setiap bangun datar.
Setelah setiap class jenis bangun datar sudah terdefinisi secara jelas, barulah bisa digunakan untuk menghitung luas dan kelilingnya.
# menghitung luas dan keliling persegi panjang dengan p = 10 dan l = 5
a = PersegiPanjang()
a.panjang = 10
a.lebar = 5
print("Luas persegi panjang:", a.hitungLuas())
print("Keliling persegi panjang:", a.hitungKeliling())
# menghitung luas dan keliling lingkaran berjejari 10
b = Lingkaran()
b.jejari = 10
print("Luas lingkaran:", b.hitungLuas())
print("Keliling lingkaran:", b.hitungKeliling())
dan output yang dihasilkan adalah
Luas persegi panjang: 50
Keliling persegi panjang: 30
Luas lingkaran: 314.0
Keliling lingkaran: 62.800000000000004
Demikian penjelasan penerapan abstraksi di Python. Mudah bukan penerapannya. Semoga artikel ini dapat dipahami dengan baik dan dapat bermanfaat 🙂

