Kelas Abstrak di Jawa

1. Ikhtisar

Ada banyak kasus saat implementasi kontrak dimana kita ingin menunda beberapa bagian implementasi untuk diselesaikan nanti. Kita dapat dengan mudah melakukannya di Java melalui kelas abstrak.

Dalam tutorial ini, kita akan mempelajari dasar-dasar kelas abstrak di Java, dan dalam kasus apa mereka bisa membantu .

2. Konsep Kunci untuk Kelas Abstrak

Sebelum mendalami kapan harus menggunakan kelas abstrak, mari kita lihat karakteristik mereka yang paling relevan :

  • Kami mendefinisikan kelas abstrak dengan pengubah abstrak sebelum kata kunci kelas
  • Kelas abstrak dapat dijadikan subkelas, tetapi tidak dapat dibuat instance-nya
  • Jika sebuah kelas mendefinisikan satu atau lebih metode abstrak , maka kelas itu sendiri harus dideklarasikan sebagai abstrak
  • Kelas abstrak dapat mendeklarasikan metode abstrak dan konkret
  • Subclass yang diturunkan dari kelas abstrak harus mengimplementasikan semua metode abstrak kelas dasar atau menjadi abstrak itu sendiri

Untuk lebih memahami konsep ini, kami akan membuat contoh sederhana.

Mari kita buat kelas abstrak dasar kita mendefinisikan API abstrak dari permainan papan:

public abstract class BoardGame { //... field declarations, constructors public abstract void play(); //... concrete methods }

Kemudian, kita bisa membuat subclass yang mengimplementasikan metode play :

public class Checkers extends BoardGame { public void play() { //... implementation } }

3. Kapan Menggunakan Kelas Abstrak

Sekarang, mari kita analisis beberapa skenario umum di mana kita harus lebih memilih kelas abstrak daripada antarmuka dan kelas konkret:

  • Kami ingin merangkum beberapa fungsi umum di satu tempat (penggunaan kembali kode) yang akan dibagikan oleh beberapa subkelas terkait
  • Kita perlu mendefinisikan sebagian API yang subclass kita dapat dengan mudah memperluas dan memperbaiki
  • Subclass perlu mewarisi satu atau beberapa metode atau kolom umum dengan pengubah akses yang dilindungi

Ingatlah bahwa semua skenario ini adalah contoh yang baik dari kepatuhan penuh berbasis warisan pada prinsip Terbuka / Tertutup.

Selain itu, karena penggunaan kelas abstrak secara implisit berhubungan dengan tipe dasar dan subtipe, kami juga memanfaatkan Polimorfisme.

Perhatikan bahwa penggunaan ulang kode adalah alasan yang sangat kuat untuk menggunakan kelas abstrak, selama hubungan "is-a" dalam hierarki kelas dipertahankan.

Dan Java 8 menambahkan kerut lainnya dengan metode default, yang terkadang menggantikan kebutuhan untuk membuat kelas abstrak sama sekali.

4. Contoh Hirarki Pembaca File

Untuk memahami lebih jelas fungsionalitas yang dibawa kelas abstrak ke tabel, mari kita lihat contoh lain.

4.1. Mendefinisikan Kelas Abstrak Basis

Jadi, jika kami ingin memiliki beberapa jenis pembaca file, kami mungkin membuat kelas abstrak yang merangkum apa yang umum untuk membaca file:

public abstract class BaseFileReader { protected Path filePath; protected BaseFileReader(Path filePath) { this.filePath = filePath; } public Path getFilePath() { return filePath; } public List readFile() throws IOException { return Files.lines(filePath) .map(this::mapFileLine).collect(Collectors.toList()); } protected abstract String mapFileLine(String line); }

Perhatikan bahwa kami telah membuat filePath terlindungi sehingga subclass dapat mengaksesnya jika diperlukan. Lebih penting lagi, kami meninggalkan sesuatu yang belum selesai: bagaimana benar-benar mengurai baris teks dari konten file.

Rencana kami sederhana: sementara kelas konkret kami tidak masing-masing memiliki cara khusus untuk menyimpan jalur file atau menelusuri file, mereka masing-masing memiliki cara khusus untuk mengubah setiap baris.

Pada pandangan pertama, BaseFileReader mungkin tampak tidak diperlukan. Namun, ini adalah dasar dari desain yang bersih dan mudah diperpanjang. Dari situ, kami dapat dengan mudah mengimplementasikan berbagai versi pembaca file yang dapat berfokus pada logika bisnis unik mereka .

4.2. Mendefinisikan Subclass

Implementasi alami mungkin adalah salah satu yang mengubah konten file menjadi huruf kecil:

public class LowercaseFileReader extends BaseFileReader { public LowercaseFileReader(Path filePath) { super(filePath); } @Override public String mapFileLine(String line) { return line.toLowerCase(); } }

Atau yang lain mungkin salah satu yang mengubah konten file menjadi huruf besar:

public class UppercaseFileReader extends BaseFileReader { public UppercaseFileReader(Path filePath) { super(filePath); } @Override public String mapFileLine(String line) { return line.toUpperCase(); } }

Seperti yang dapat kita lihat dari contoh sederhana ini, setiap subclass dapat berfokus pada perilakunya yang unik tanpa perlu menentukan aspek lain dari pembacaan file.

4.3. Menggunakan Subclass

Terakhir, menggunakan kelas yang mewarisi dari kelas abstrak tidak berbeda dengan kelas konkret lainnya:

@Test public void givenLowercaseFileReaderInstance_whenCalledreadFile_thenCorrect() throws Exception { URL location = getClass().getClassLoader().getResource("files/test.txt") Path path = Paths.get(location.toURI()); BaseFileReader lowercaseFileReader = new LowercaseFileReader(path); assertThat(lowercaseFileReader.readFile()).isInstanceOf(List.class); }

Demi kesederhanaan, file target terletak di bawah folder src / main / resources / files . Karenanya, kami menggunakan loader kelas aplikasi untuk mendapatkan jalur file contoh. Jangan ragu untuk melihat tutorial kami tentang pemuat kelas di Java.

5. Kesimpulan

Dalam artikel singkat ini, kita mempelajari dasar-dasar kelas abstrak di Java, dan kapan menggunakannya untuk mencapai abstraksi dan merangkum implementasi umum di satu tempat .

Seperti biasa, semua contoh kode yang ditampilkan dalam tutorial ini tersedia di GitHub.