Hai! Mari kita bicara tentang kelas abstrak di Jawa.Contoh konkrit kelas abstrak di Java - 1

Mengapa kelas disebut "abstrak"?

Anda mungkin ingat apa itu abstraksi — kita telah membahasnya sebelumnya :) Jika Anda lupa, jangan khawatir. Ingat, ini adalah prinsip OOP yang mengatakan, saat mendesain kelas dan membuat objek, Anda harus merepresentasikan hanya properti utama entitas dan membuang properti sekunder. Sebagai contoh, jika kita sedang mendesain sebuah SchoolTeacherkelas, tinggi badan mungkin tidak akan menjadi properti yang diperlukan dari seorang guru. Memang sifat ini tidak penting bagi seorang guru. Namun jika kita membuat BasketballPlayerkelas, maka tinggi akan menjadi salah satu karakteristik yang paling penting. Nah, kelas abstrakadalah yang paling abstrak, "benda kerja kasar" untuk sekelompok kelas masa depan. Benda kerja tidak dapat digunakan secara langsung — terlalu "kasar". Tapi itu mendefinisikan keadaan dan perilaku karakteristik tertentu yang akan dimiliki kelas masa depan - keturunan dari kelas abstrak.

Contoh kelas abstrak di Java

Pertimbangkan contoh sederhana dengan mobil:

public abstract class Car {

   private String model;
   private String color;
   private int maxSpeed;
  
   public abstract void gas();

   public abstract void brake();

   public String getModel() {
       return model;
   }

   public void setModel(String model) {
       this.model = model;
   }

   public String getColor() {
       return color;
   }

   public void setColor(String color) {
       this.color = color;
   }

   public int getMaxSpeed() {
       return maxSpeed;
   }

   public void setMaxSpeed(int maxSpeed) {
       this.maxSpeed = maxSpeed;
   }
}
Seperti inilah tampilan kelas abstrak yang paling sederhana. Seperti yang Anda lihat, tidak ada yang istimewa :) Mengapa kami membutuhkan ini? Pertama, ini memberikan deskripsi paling abstrak tentang entitas yang kita butuhkan — sebuah mobil. Kata kunci abstrak berarti sesuatu di sini. Di dunia nyata, tidak ada yang namanya "hanya sebuah mobil". Ada truk, mobil balap, sedan, coupe, dan SUV. Kelas abstrak kita hanyalah sebuah "cetak biru" yang nantinya akan kita gunakan untuk membuat kelas mobil tertentu.

public class Sedan extends Car {
  
   @Override
   public void gas() {
       System.out.println("The sedan is accelerating!");
   }

   @Override
   public void brake() {
       System.out.println("The sedan is slowing down!");
   }
  
}
Dalam banyak hal, ini mirip dengan apa yang kita bicarakan dalam pelajaran tentang warisan. Hanya dalam kasus itu kami memiliki Carkelas yang metodenya tidak abstrak. Tetapi solusi semacam itu memiliki beberapa kelemahan yang diperbaiki dalam kelas abstrak. Pertama dan terpenting, instance dari kelas abstrak tidak dapat dibuat:

public class Main {

   public static void main(String[] args) {

       Car car = new Car(); // Error! The Car class is abstract!
   }
}
Pembuat Java sengaja membuat "fitur" ini. Sekali lagi, ingat: kelas abstrak hanyalah cetak biru untuk kelas "biasa" mendatang . Anda tidak memerlukan salinan cetak biru, bukan? Demikian pula, tidak perlu membuat turunan dari kelas abstrak :) Dan jika Carkelas tersebut tidak abstrak, maka kita dapat dengan mudah membuat turunannya:

public class Car {

   private String model;
   private String color;
   private int maxSpeed;
  
   public void go() {
       // ...some logic
   }

   public  void brake() {
       // ...some logic
   }
}


public class Main {

   public static void main(String[] args) {

       Car car = new Car(); // This is okay. The car is created.
   }
}
Saat ini, program kami memiliki semacam mobil yang tidak dapat dipahami. Ini bukan truk, bukan mobil balap, dan bukan sedan, tapi tidak terlalu jelas apa itu. Ini adalah "hanya sebuah mobil" yang tidak ada dalam kenyataan. Contoh yang sama dapat diberikan pada hewan. Bayangkan jika program Anda memiliki Animalobjek (" hanya binatang "). Tidak jelas apa jenisnya, milik keluarga apa, atau karakteristik apa yang dimilikinya. Akan aneh melihat satu dalam sebuah program. Tidak ada "hanya binatang" di alam. Hanya anjing, kucing, rubah, tahi lalat, dll. Kelas abstrak menyelamatkan kita dari " objek saja ". Mereka memberi kita keadaan dan perilaku dasar. Misalnya semua mobil pasti memiliki model , warna dan top speed, dan mereka juga harus bisa menginjak gas dan rem . Itu dia. Ini adalah cetak biru abstrak umum yang akan Anda gunakan nanti untuk mendesain kelas yang Anda butuhkan. Catatan: dua metode di kelas abstrak juga abstract , yang berarti mereka tidak memiliki implementasi sama sekali. Alasannya sama: kelas abstrak tidak membuat "perilaku default" untuk "hanya mobil". Mereka hanya menunjukkan apa yang harus dapat dilakukan oleh setiap mobil. Yang mengatakan, jika Anda membutuhkan perilaku default, Anda dapat mengimplementasikan metode dalam kelas abstrak. Java tidak melarang ini:

public abstract class Car {

   private String model;
   private String color;
   private int maxSpeed;

   public void gas() {
       System.out.println("Accelerating!");
   }

   public abstract void brake();
  
   // Getters and setters
}


public class Sedan extends Car {

   @Override
   public void brake() {
       System.out.println("The sedan is slowing down!");
   }

}

public class Main {

   public static void main(String[] args) {

       Sedan sedan = new Sedan();
       sedan.gas();
   }
}
Keluaran konsol:
Accelerating!
Seperti yang Anda lihat, kami menerapkan satu metode di kelas abstrak, tetapi tidak yang lain. Akibatnya, perilaku Sedankelas kami dibagi menjadi dua bagian: jika kami memanggil metodenya gas(), perilaku tersebut "ditarik" dari Carkelas induk abstrak, dan kami menerapkan brake()metode tersebut di Sedankelas. Itu sangat nyaman dan fleksibel. Tapi kelas kita tidak begitu abstrak sekarang, bukan ? Bagaimanapun, itu benar-benar menerapkan setengah dari metode. Faktanya adalah — dan ini adalah fitur yang sangat penting — sebuah kelas bersifat abstrak bahkan jika salah satu metodenya abstrak. Satu metode dari dua, atau satu dari seribu — tidak masalah. Kami bahkan dapat mengimplementasikan semua metode, tidak meninggalkan yang abstrak. Hasilnya akan menjadi kelas abstrak tanpa metode abstrak. Ini mungkin pada prinsipnya - kompiler tidak akan menghasilkan kesalahan apa pun - tetapi lebih baik tidak melakukan ini, karena kata abstrak kehilangan maknanya. Rekan pemrogram Anda juga akan sangat terkejut melihat ini :/ Konon, jika suatu metode ditandai sebagai abstrak, setiap kelas keturunan harus mengimplementasikannya atau dideklarasikan sebagai abstrak. Jika tidak, kompiler akan membuat kesalahan. Tentu saja, setiap kelas hanya dapat mewarisi satu kelas abstrak, jadi tidak ada perbedaan antara kelas abstrak dan reguler dalam hal pewarisan. Tidak masalah jika kita mewarisi kelas abstrak atau biasa — hanya ada satu kelas induk.

Mengapa Java tidak memiliki banyak pewarisan kelas

Kami telah mengatakan bahwa tidak ada pewarisan berganda di Jawa, tetapi kami tidak benar-benar menyelidiki alasannya. Mari kita coba melakukannya sekarang. Faktanya adalah jika Java memang memiliki pewarisan berganda, maka kelas anak tidak akan dapat memutuskan perilaku mana yang akan dipilih. Katakanlah kita memiliki dua kelas: Toasterdan NuclearBomb:

public class Toaster {
  
  
 public void on() {

       System.out.println("The toaster is on. We're toasting!");
   }
  
   public void off() {

       System.out.println("The toaster is off!");
   }
}


public class NuclearBomb {

   public void on() {

       System.out.println("Boom!");
   }
}
Seperti yang Anda lihat, kedua kelas memiliki on()metode. Untuk pemanggang roti, metodenya dimulai dengan membuat roti bakar, tetapi dalam kasus bom nuklir, metode ini memicu ledakan. Uh-oh :/ Sekarang bayangkan Anda telah memutuskan (jangan tanya kenapa!) untuk membuat sesuatu di antaranya. Inilah kelas Anda: MysteriousDevice! Kode ini tidak akan berfungsi, tentu saja. Kami menyajikannya hanya sebagai contoh "apa yang mungkin terjadi":

public class MysteriousDevice extends Toster, NuclearBomb {

   public static void main(String[] args) {
      
       MysteriousDevice mysteriousDevice = new MysteriousDevice();
       mysteriousDevice.on(); // And what should happen here? Will we get toast or a nuclear apocalypse?
   }
}
Mari kita lihat apa yang kita punya. Perangkat misterius itu berasal dari Toaster dan NuclearBomb secara bersamaan. Keduanya memiliki on()metode. Akibatnya, tidak jelas implementasi mana yang harus dijalankan jika kita memanggil on()sebuah MysteriousDeviceobjek. Objek tidak akan mengerti. Dan yang terpenting, NuclearBomb tidak memiliki off()metode, jadi jika kita tidak menebak dengan benar, maka tidak mungkin mematikan perangkat. Contoh konkret kelas abstrak di Java - 2"Kesalahpahaman" ini, ketika tidak jelas perilaku mana yang harus dijalankan, justru menjadi alasan mengapa pencipta Java menolak pewarisan berganda. Yang mengatakan, Anda akan belajar bahwa kelas Java dapat mengimplementasikan banyak antarmuka.