JavaRush /Java Blog /Random-ID /Rehat kopi #90. 4 Pilar Pemrograman Berorientasi Objek

Rehat kopi #90. 4 Pilar Pemrograman Berorientasi Objek

Dipublikasikan di grup Random-ID
Sumber: The Geek Asian Mari kita lihat empat dasar pemrograman berorientasi objek dan mencoba memahami cara kerjanya. Pemrograman berorientasi objek (OOP) adalah salah satu paradigma pemrograman utama. Ini bisa mudah dan sederhana atau, sebaliknya, sangat rumit. Itu semua tergantung pada bagaimana Anda memutuskan untuk mengembangkan aplikasi Anda. Rehat kopi #90.  4 pilar pemrograman berorientasi objek - 1Ada 4 pilar OOP:
  1. Enkapsulasi.
  2. Warisan.
  3. Abstraksi.
  4. Polimorfisme.
Sekarang kita akan membahas masing-masingnya dengan penjelasan singkat dan contoh kode nyata.

1. Enkapsulasi

Kita semua telah mempelajari enkapsulasi sebagai penyembunyian elemen data dan memungkinkan pengguna mengakses data menggunakan metode publik. Kami menyebutnya getter dan setter. Sekarang mari kita lupakan hal ini dan temukan definisi yang lebih sederhana. Enkapsulasi adalah metode yang membatasi pengguna untuk mengubah anggota data atau variabel kelas secara langsung untuk menjaga integritas data. Bagaimana kita melakukan ini? Kami membatasi akses ke variabel dengan mengalihkan pengubah akses ke privat dan mengekspos metode publik yang dapat digunakan untuk mengakses data. Mari kita lihat contoh spesifik di bawah ini. Ini akan membantu kita memahami bagaimana kita dapat menggunakan enkapsulasi untuk menjaga integritas data. Tanpa enkapsulasi:
/**
 * @author thegeekyasian.com
 */
public class Account {

  public double balance;

  public static void main(String[] args) {

  	Account theGeekyAsianAccount = new Account();

  	theGeekyAsianAccount.balance = -54;
  }
}
Pada cuplikan kode di atas, metode main() mengakses variabel saldo secara langsung. Hal ini memungkinkan pengguna untuk menetapkan nilai ganda apa pun ke variabel saldo kelas Akun . Kita dapat kehilangan integritas data dengan mengizinkan siapa pun menyetel saldo ke nomor yang tidak valid, misalnya -54 dalam kasus ini. Dengan enkapsulasi:
/**
 * @author thegeekyasian.com
 */
public class Account {

  private double balance;

  public void setBalance(double balance) {

    if(balance >= 0) { // Validating input data in order to maintain data integrity
	  this.balance = balance;
    }

    throw new IllegalArgumentException("Balance cannot be less than zero (0)");
  }

  public static void main(String[] args) {

  	Account theGeekyAsianAccount = new Account();

  	theGeekyAsianAccount.setBalance(1); // Valid input - Allowed
  	theGeekyAsianAccount.setBalance(-55); // Stops user and throws exception
  }
}
Dalam kode ini, kami telah membatasi akses ke variabel saldo dan menambahkan metode setBalance() yang memungkinkan pengguna menyetel nilai saldo untuk Account . Penyetel memeriksa nilai yang diberikan sebelum menugaskannya ke variabel. Jika nilainya kurang dari nol, pengecualian akan diberikan. Hal ini memastikan bahwa integritas data tidak terganggu. Setelah menjelaskan contoh di atas, saya berharap nilai enkapsulasi sebagai salah satu dari empat pilar OOP menjadi jelas.

2. Warisan

Warisan adalah metode untuk memperoleh properti dari kelas lain yang memiliki fitur umum yang sama. Hal ini memungkinkan kami meningkatkan penggunaan kembali dan mengurangi duplikasi kode. Metode ini juga memiliki prinsip interaksi anak-orang tua, ketika elemen anak mewarisi properti induknya. Mari selami dua contoh singkat dan lihat bagaimana pewarisan membuat kode lebih sederhana dan lebih dapat digunakan kembali. Tanpa warisan:
/**
 * @author thegeekyasian
 */
public class Rectangle {

  private int width;
  private int height;

  public Rectangle(int width, int height) {
	this.width = width;
	this.height = height;
  }

  public int getArea() {
	return width * height;
  }
}

public class Square {

  private int width; // Duplicate property, also used in class Rectangle

  public Square(int width) {
	this.width = width;
  }

  public int getArea() { // Duplicate method, similar to the class Rectangle
	return this.width * this.width;
  }
}
Dua kelas serupa berbagi properti lebar dan metode getArea() . Kita dapat meningkatkan penggunaan kembali kode dengan melakukan sedikit refactoring dimana kelas Square akhirnya mewarisi dari kelas Rectangle . Dengan warisan:
/**
 * @author thegeekyasian
 */
public class Rectangle {

  private int width;
  private int height;

  public Rectangle(int width, int height) {
	this.width = width;
	this.height = height;
  }

  public int getArea() {
	return width * height;
  }
}

public class Square extends Rectangle {

  public Square(int width) {
	super(width, width); // A rectangle with the same height as width is a square
  }
}
Dengan hanya memperluas kelas Rectangle , kita mendapatkan kelas Square sebagai tipe Rectangle . Artinya ia mewarisi semua properti umum pada Square dan Rectangle . Pada contoh di atas, kita melihat bagaimana pewarisan memainkan peran penting dalam membuat kode dapat digunakan kembali. Hal ini juga memungkinkan suatu kelas untuk mewarisi perilaku kelas induknya.

3. Abstraksi

Abstraksi adalah teknik menyajikan detail penting saja kepada pengguna dengan menyembunyikan detail objek yang tidak perlu atau tidak relevan. Ini membantu mengurangi kompleksitas operasional di sisi pengguna. Abstraksi memungkinkan kami menyediakan antarmuka sederhana kepada pengguna tanpa meminta detail rumit untuk melakukan suatu tindakan. Sederhananya, ini memberi pengguna kemampuan untuk mengendarai mobil tanpa mengharuskan mereka memahami secara pasti cara kerja mesin. Mari kita lihat contohnya terlebih dahulu dan kemudian diskusikan bagaimana abstraksi membantu kita.
/**
* @author thegeekyasian.com
*/
public class Car {

  public void lock() {}
  public void unlock() {}

  public void startCar() {

	checkFuel();
	checkBattery();
	whatHappensWhenTheCarStarts();
  }

  private void checkFuel() {
	// Check fuel level
  }

  private void checkBattery() {
	// Check car battery
  }

  private void whatHappensWhenTheCarStarts() {
	// Magic happens here
  }
}
Dalam kode di atas, metode lock() , unlock() dan startCar() bersifat publik dan sisanya bersifat pribadi untuk kelas. Kami telah mempermudah pengguna untuk “mengendarai mobil.” Tentu saja, dia dapat memeriksa checkFuel() dan checkBattery() secara manual sebelum menyalakan mobil dengan startCar() , tetapi itu hanya akan mempersulit prosesnya. Dengan kode di atas, yang perlu dilakukan pengguna hanyalah menggunakan startCar() dan kelas akan mengurus sisanya. Inilah yang kami sebut abstraksi.

4. Polimorfisme

Pilar terakhir dan terpenting dari empat pilar OOP adalah polimorfisme. Polimorfisme berarti “banyak bentuk.” Seperti namanya, ini adalah fungsi yang memungkinkan Anda melakukan suatu tindakan dengan berbagai cara atau berbeda. Ketika kita berbicara tentang polimorfisme, tidak banyak yang perlu dibahas kecuali kita membicarakan jenis-jenisnya. Ada dua jenis polimorfisme:
  1. Metode kelebihan beban - polimorfisme statis (Static Binding).
  2. Metode penggantian adalah polimorfisme dinamis (Dynamic Binding).
Mari kita bahas masing-masing jenis ini dan lihat apa perbedaan di antara keduanya.

Metode kelebihan beban - polimorfisme statis:

Kelebihan metode atau polimorfisme statis, juga dikenal sebagai Pengikatan Statis atau pengikatan waktu kompilasi, adalah jenis di mana pemanggilan metode ditentukan pada waktu kompilasi. Kelebihan metode memungkinkan kita memiliki beberapa metode dengan nama yang sama, memiliki tipe data parameter berbeda, atau jumlah parameter berbeda, atau keduanya. Namun pertanyaannya adalah, mengapa metode kelebihan beban (atau polimorfisme statis) berguna? Mari kita lihat contoh di bawah ini untuk lebih memahami metode kelebihan beban. Tanpa metode yang membebani:
/**
* @author thegeekyasian.com
*/
public class Number {

  public void sumInt(int a, int b) {
	System.out.println("Sum: " + (a + b));
  }

  public void sumDouble(double a, double b) {
	System.out.println("Sum: " + (a + b));
  }

  public static void main(String[] args) {

	Number number = new Number();

	number.sumInt(1, 2);
	number.sumDouble(1.8, 2.5);
  }
}
Pada contoh di atas, kita membuat dua metode dengan nama berbeda, hanya untuk menjumlahkan dua tipe angka berbeda. Jika kita melanjutkan implementasi serupa, kita akan memiliki beberapa metode dengan nama berbeda. Hal ini akan mengurangi kualitas dan ketersediaan kode. Untuk memperbaikinya, kita dapat menggunakan metode kelebihan beban dengan menggunakan nama yang sama untuk metode yang berbeda. Ini akan memungkinkan pengguna memiliki satu opsi sebagai titik masuk untuk menjumlahkan berbagai jenis angka. Metode yang berlebihan berfungsi ketika dua atau lebih metode memiliki nama yang sama tetapi parameternya berbeda. Tipe pengembalian bisa sama atau berbeda. Tetapi jika dua metode memiliki nama yang sama, parameter yang sama, tetapi tipe pengembalian yang berbeda, maka hal ini akan menyebabkan kelebihan beban dan kesalahan kompilasi! Dengan kelebihan metode:
/**
* @author thegeekyasian.com
*/
public class Number {

  public void sum(int a, int b) {
	System.out.println("Sum: " + (a + b));
  }

  public void sum(double a, double b) {
	System.out.println("Sum: " + (a + b));
  }

  public static void main(String[] args) {

	Number number = new Number();

	number.sum(1, 2);
	number.sum(1.8, 2.5);
  }
}
Dalam kode yang sama, dengan beberapa perubahan kecil, kami dapat membebani kedua metode secara berlebihan, menjadikan nama keduanya sama. Pengguna sekarang dapat menentukan tipe data spesifiknya sebagai parameter metode. Ia kemudian akan melakukan tindakan berdasarkan tipe data yang disediakan. Pengikatan metode ini dilakukan pada waktu kompilasi karena compiler mengetahui metode mana yang akan dipanggil dengan tipe parameter yang ditentukan. Itu sebabnya kami menyebutnya pengikatan waktu kompilasi.

Penggantian metode - polimorfisme dinamis:

Tidak seperti metode yang berlebihan, penggantian metode memungkinkan Anda memiliki tanda tangan yang sama persis dengan beberapa metode, namun metode tersebut harus berada di beberapa kelas yang berbeda. Pertanyaannya, apa istimewanya? Kelas-kelas ini memiliki hubungan IS-A, yaitu mereka harus mewarisi satu sama lain. Dengan kata lain, dalam penggantian metode atau polimorfisme dinamis, metode diproses secara dinamis pada waktu proses ketika metode tersebut dipanggil. Hal ini dilakukan berdasarkan referensi ke objek yang diinisialisasi. Berikut adalah contoh kecil dari penggantian metode:
/**
* @author thegeekyasian.com
*/
public class Animal {

  public void walk() {
	System.out.println("Animal walks");
  }
}

public class Cat extends Animal {

  @Override
  public void walk() {
	System.out.println("Cat walks");
  }
}

public class Dog extends Animal {

  @Override
  public void walk() {
	System.out.println("Dog walks");
  }
}

public class Main {

  public static void main(String[] args) {

	Animal animal = new Animal();
	animal.walk(); // Animal walks

	Cat cat = new Cat();
	cat.walk(); // Cat walks

	Dog dog = new Dog();
	dog.walk(); // Dog walks

	Animal animalCat = new Cat(); // Dynamic Polymorphism
	animalCat.walk(); // Cat walks

	Animal animalDog = new Dog(); // Dynamic Polymorphism
	animalDog.walk(); //Dog walks
  }
}
Dalam contoh utama ini, kami secara dinamis menetapkan objek bertipe “Anjing” dan “Kucing” untuk mengetik “Hewan”. Hal ini memungkinkan kita memanggil metode walk() pada instance yang direferensikan secara dinamis saat runtime. Kita dapat melakukan ini dengan menggunakan metode overriding (atau polimorfisme dinamis). Demikianlah pembahasan singkat kita tentang empat pilar OOP dan semoga bermanfaat bagi Anda.
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION