Kelas Abstrak di Jawa

1. Gambaran keseluruhan

Terdapat banyak kes semasa melaksanakan kontrak di mana kami ingin menangguhkan beberapa bahagian pelaksanaan yang akan diselesaikan kemudian. Kita dapat melakukannya dengan mudah di Jawa melalui kelas abstrak.

Dalam tutorial ini, kita akan mempelajari asas-asas kelas abstrak di Jawa, dan dalam keadaan apa mereka dapat membantu .

2. Konsep Utama untuk Kelas Abstrak

Sebelum mempelajari kelas abstrak, mari kita lihat ciri-ciri mereka yang paling relevan :

  • Kami menentukan kelas abstrak dengan pengubah abstrak sebelum kata kunci kelas
  • Kelas abstrak dapat diklasifikasikan, tetapi tidak dapat disusun
  • Sekiranya kelas menentukan satu atau lebih kaedah abstrak , maka kelas itu sendiri mesti dinyatakan abstrak
  • Kelas abstrak dapat menyatakan kaedah abstrak dan konkrit
  • Subkelas yang berasal dari kelas abstrak mesti melaksanakan semua kaedah abstrak kelas asas atau abstrak itu sendiri

Untuk memahami konsep ini dengan lebih baik, kami akan membuat contoh mudah.

Mari kita kelas abstrak asas kami menentukan API abstrak permainan papan:

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

Kemudian, kita dapat membuat subkelas yang menerapkan kaedah bermain :

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

3. Bilakah Menggunakan Kelas Abstrak

Sekarang, mari kita menganalisis beberapa senario khas di mana kita harus memilih kelas abstrak daripada kelas antara muka dan konkrit:

  • Kami ingin merangkumi beberapa fungsi umum di satu tempat (penggunaan semula kod) yang akan dikongsi oleh beberapa subkelas yang berkaitan
  • Kita perlu menentukan sebahagian API yang boleh diperluas dan diperbaiki oleh subkelas kita
  • Subkelas perlu mewarisi satu atau lebih kaedah atau bidang biasa dengan pengubah akses dilindungi

Mari kita ingat bahawa semua senario ini adalah contoh yang baik dari kepatuhan penuh berdasarkan warisan terhadap prinsip Buka / Tertutup.

Lebih-lebih lagi, kerana penggunaan kelas abstrak secara langsung menyiratkan jenis dan subtipe asas, kami juga memanfaatkan Polimorfisme.

Perhatikan bahawa penggunaan semula kod adalah alasan yang sangat kuat untuk menggunakan kelas abstrak, selagi hubungan "is-a" dalam hierarki kelas dipelihara.

Dan Java 8 menambah kerutan lain dengan kaedah lalai, yang kadang-kadang dapat menggantikan keperluan untuk membuat kelas abstrak sama sekali.

4. Contoh Hierarki Pembaca Fail

Untuk memahami dengan lebih jelas fungsi yang dibawa oleh kelas abstrak, mari kita lihat contoh lain.

4.1. Mendefinisikan Kelas Abstrak Pangkalan

Oleh itu, jika kita ingin mempunyai beberapa jenis pembaca fail, kita mungkin membuat kelas abstrak yang merangkumi perkara biasa untuk membaca fail:

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 bahawa kami telah membuat filePath dilindungi sehingga subkelas dapat mengaksesnya jika diperlukan. Lebih penting lagi, kami telah membuat sesuatu yang tidak diendahkan: bagaimana cara menguraikan sebaris teks dari kandungan fail.

Rancangan kami mudah: sementara kelas konkrit kami tidak masing-masing mempunyai cara khas untuk menyimpan jalan fail atau berjalan melalui fail, mereka masing-masing akan mempunyai cara khas untuk mengubah setiap baris.

Pada pandangan pertama, BaseFileReader mungkin kelihatan tidak perlu. Namun, ia adalah asas reka bentuk yang bersih dan mudah diperpanjang. Dari itu, kita dapat dengan mudah menerapkan versi pembaca fail yang berbeza yang dapat menumpukan pada logik perniagaan mereka yang unik .

4.2. Mendefinisikan Subkelas

Pelaksanaan semula jadi mungkin adalah yang mengubah kandungan fail 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 yang mengubah kandungan fail 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 subkelas dapat memusatkan perhatian pada tingkah laku uniknya tanpa perlu menentukan aspek lain dalam membaca fail.

4.3. Menggunakan Subkelas

Akhirnya, menggunakan kelas yang mewarisi dari abstrak tidak berbeza dengan kelas konkrit lain:

@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, fail sasaran terletak di bawah folder src / main / resources / files . Oleh itu, kami menggunakan pemuat kelas aplikasi untuk mendapatkan jalan fail contoh. Jangan ragu untuk melihat tutorial kami mengenai pemuat kelas di Java.

5. Kesimpulan

Dalam artikel ringkas ini, kami mempelajari asas-asas kelas abstrak di Jawa, dan kapan menggunakannya untuk mencapai abstraksi dan merangkumi pelaksanaan umum di satu tempat .

Seperti biasa, semua contoh kod yang ditunjukkan dalam tutorial ini terdapat di GitHub.