CodeGym/Blog Java/rawak/Perbezaan antara kelas abstrak dan antara muka
John Squirrels
Tahap
San Francisco

Perbezaan antara kelas abstrak dan antara muka

Diterbitkan dalam kumpulan
Hai! Dalam pelajaran ini, kita akan bercakap tentang cara kelas abstrak berbeza daripada antara muka dan mempertimbangkan beberapa contoh dengan kelas abstrak biasa. Perbezaan antara kelas abstrak dan antara muka - 1Kami telah menumpukan pelajaran yang berasingan kepada perbezaan antara kelas abstrak dan antara muka, kerana topik ini sangat penting. Anda akan ditanya tentang perbezaan antara konsep ini dalam 90% temu bual akan datang. Ini bermakna anda harus memastikan untuk mengetahui apa yang anda baca. Dan jika anda tidak memahami sepenuhnya sesuatu, baca sumber tambahan. Jadi, kita tahu apa itu kelas abstrak dan apa itu antara muka. Sekarang kita akan membincangkan perbezaan mereka.
  1. Antara muka hanya menerangkan tingkah laku. Ia tidak mempunyai negeri. Tetapi kelas abstrak termasuk keadaan: ia menerangkan kedua-duanya.

    Sebagai contoh, ambil Birdkelas abstrak dan CanFlyantara muka:

    public abstract class Bird {
       private String species;
       private int age;
    
       public abstract void fly();
    
       public String getSpecies() {
           return species;
       }
    
       public void setSpecies(String species) {
           this.species = species;
       }
    
       public int getAge() {
           return age;
       }
    
       public void setAge(int age) {
           this.age = age;
       }
    }

    Mari buat MockingJaykelas burung dan jadikan ia mewarisi Bird:

    public class MockingJay extends Bird {
    
       @Override
       public void fly() {
           System.out.println("Fly, bird!");
       }
    
       public static void main(String[] args) {
    
           MockingJay someBird = new MockingJay();
           someBird.setAge(19);
           System.out.println(someBird.getAge());
       }
    }

    Seperti yang anda lihat, kami boleh mengakses keadaan kelas abstrak dengan mudah — speciesdan agepembolehubahnya.

    Tetapi jika kita cuba melakukan perkara yang sama dengan antara muka, gambarnya berbeza. Kita boleh cuba menambah pembolehubah kepadanya:

    public interface CanFly {
    
       String species = new String();
       int age = 10;
    
       public void fly();
    }
    
    public interface CanFly {
    
       private String species = new String(); // Error
       private int age = 10; // Another error
    
       public void fly();
    }

    Kami tidak boleh mengisytiharkan pembolehubah peribadi dalam antara muka. kenapa? Kerana pengubah suai peribadi dicipta untuk menyembunyikan pelaksanaan daripada pengguna. Dan antara muka tidak mempunyai pelaksanaan di dalamnya: tidak ada apa-apa untuk disembunyikan.

    Antara muka hanya menerangkan tingkah laku. Oleh itu, kami tidak boleh melaksanakan getter dan setter di dalam antara muka. Ini adalah sifat antara muka: mereka diperlukan untuk berfungsi dengan tingkah laku, bukan keadaan.

    Java 8 memperkenalkan kaedah lalai untuk antara muka yang mempunyai pelaksanaan. Anda sudah tahu tentang mereka, jadi kami tidak akan mengulangi diri kami sendiri.

  2. Kelas abstrak menghubungkan dan menyatukan kelas yang sangat berkait rapat. Pada masa yang sama, antara muka tunggal boleh dilaksanakan oleh kelas yang sama sekali tidak mempunyai persamaan.

    Mari kita kembali kepada contoh kita dengan burung.

    Kelas abstrak kami Birddiperlukan untuk mencipta burung yang berdasarkan kelas itu. Hanya burung dan tidak ada yang lain! Sudah tentu, akan ada pelbagai jenis burung.

    Perbezaan antara kelas abstrak dan antara muka - 2

    Dengan CanFlyantara muka, semua orang meneruskan dengan cara mereka sendiri. Ia hanya menerangkan tingkah laku (terbang) yang dikaitkan dengan namanya. Banyak benda tak berkaitan 'boleh terbang'.

    Perbezaan antara kelas abstrak dan antara muka - 3

    4 entiti ini tidak berkaitan antara satu sama lain. Mereka bukan semua hidup. Namun, mereka semua CanFly.

    Kami tidak dapat menerangkannya menggunakan kelas abstrak. Mereka tidak berkongsi keadaan yang sama atau medan yang sama. Untuk menentukan pesawat, kita mungkin memerlukan medan untuk model, tahun pengeluaran dan bilangan penumpang maksimum. Untuk Carlson, kami memerlukan ladang untuk semua gula-gula yang dia makan hari ini, dan senarai permainan yang akan dia mainkan bersama adik lelakinya. Untuk nyamuk, ...eh... Saya pun tak tahu... Mungkin, 'tahap kegusaran'? :)

    Intinya ialah kita tidak boleh menggunakan kelas abstrak untuk menerangkannya. Mereka terlalu berbeza. Tetapi mereka mempunyai tingkah laku yang dikongsi: mereka boleh terbang. Antara muka sesuai untuk menerangkan segala-galanya di dunia yang boleh terbang, berenang, melompat atau mempamerkan beberapa tingkah laku lain.

  3. Kelas boleh melaksanakan seberapa banyak antara muka yang anda mahu, tetapi mereka hanya boleh mewarisi satu kelas.

    Kami telah menyebut perkara ini lebih daripada sekali. Java tidak mempunyai berbilang warisan kelas, tetapi ia menyokong berbilang warisan antara muka. Perkara ini mengikuti sebahagian daripada yang sebelumnya: antara muka menghubungkan banyak kelas berbeza yang selalunya tidak mempunyai persamaan lain, manakala kelas abstrak dicipta untuk sekumpulan kelas yang sangat berkait rapat. Oleh itu, masuk akal bahawa anda hanya boleh mewarisi satu kelas sedemikian. Kelas abstrak menerangkan hubungan 'ialah-a'.

Antara muka standard: InputStream dan OutputStream

Kami telah pun meneliti pelbagai kelas yang bertanggungjawab untuk aliran input dan output. Mari kita pertimbangkan InputStreamdan OutputStream. Secara umum, ini bukan antara muka sama sekali, tetapi kelas abstrak sepenuhnya tulen. Sekarang anda tahu maksudnya, jadi lebih mudah untuk bekerja dengan mereka :) InputStreamialah kelas abstrak yang bertanggungjawab untuk input bait. Java mempunyai beberapa kelas yang mewarisi InputStream. Setiap daripada mereka direka untuk menerima data daripada sumber yang berbeza. Kerana InputStreammerupakan ibu bapa, ia menyediakan beberapa kaedah yang memudahkan untuk bekerja dengan aliran data. Setiap keturunan InputStreammempunyai kaedah ini:
  • int available()mengembalikan bilangan bait yang tersedia untuk dibaca;
  • close()menutup aliran input;
  • int read()mengembalikan perwakilan integer bagi bait seterusnya yang tersedia dalam strim. Jika akhir aliran telah dicapai, -1 akan dikembalikan;
  • int read(byte[] buffer)cuba membaca bait ke dalam penimbal, dan mengembalikan bilangan bait yang dibaca. Apabila ia mencapai penghujung fail, ia mengembalikan -1;
  • int read(byte[] buffer, int byteOffset, int byteCount)menulis sebahagian daripada blok bait. Ia digunakan apabila tatasusunan bait mungkin tidak diisi sepenuhnya. Apabila ia mencapai penghujung fail, ia mengembalikan -1;
  • long skip(long byteCount)melangkau byteCount byte dalam aliran input dan mengembalikan bilangan bait yang diabaikan.
Saya mengesyorkan anda mengkaji senarai lengkap kaedah . Terdapat lebih daripada sepuluh kelas kanak-kanak. Sebagai contoh, berikut adalah beberapa:
  1. FileInputStream: jenis yang paling biasa InputStream. Ia digunakan untuk membaca maklumat daripada fail;
  2. StringBufferInputStream: Satu lagi jenis InputStream. Ia menukar rentetan menjadi InputStream;
  3. BufferedInputStream: Strim input terkumpul. Ia digunakan paling kerap untuk meningkatkan prestasi.
Ingat ketika kami pergi BufferedReaderdan mengatakan bahawa anda tidak perlu menggunakannya? Apabila kita menulis:
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))
…anda tidak perlu menggunakan BufferedReader: Seorang InputStreamReaderboleh melakukan kerja itu. Tetapi BufferedReadermeningkatkan prestasi dan juga boleh membaca keseluruhan baris data dan bukannya aksara individu. Perkara yang sama berlaku untuk BufferedInputStream! Kelas mengumpul data input dalam penimbal khas tanpa sentiasa mengakses peranti input. Mari kita pertimbangkan contoh:
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.InputStream;

public class BufferedInputExample {

   public static void main(String[] args) throws Exception {
       InputStream inputStream = null;
       BufferedInputStream buffer = null;

       try {

           inputStream = new FileInputStream("D:/Users/UserName/someFile.txt");

           buffer = new BufferedInputStream(inputStream);

           while(buffer.available()>0) {

               char c = (char)buffer.read();

                System.out.println("Character read: " + c);
           }
       } catch(Exception e) {

           e.printStackTrace();

       } finally {

           inputStream.close();
           buffer.close();
       }
   }
}
Dalam contoh ini, kami membaca data daripada fail yang terletak pada komputer di ' D:/Users/UserName/someFile.txt '. Kami mencipta 2 objek — a FileInputStreamdan a BufferedInputStreamyang 'membungkusnya'. Kemudian kami membaca bait daripada fail dan menukarnya kepada aksara. Dan kami melakukannya sehingga fail tamat. Seperti yang anda lihat, tidak ada yang rumit di sini. Anda boleh menyalin kod ini dan menjalankannya pada fail sebenar pada komputer anda :) Kelas OutputStreamialah kelas abstrak yang mewakili aliran keluaran bait. Seperti yang anda sedia maklum, ini adalah bertentangan dengan InputStream. Ia tidak bertanggungjawab untuk membaca data dari suatu tempat, sebaliknya untuk menghantar data ke suatu tempat . Seperti InputStream, kelas abstrak ini memberikan semua keturunannya satu set kaedah yang mudah:
  • void close()menutup aliran keluaran;
  • void flush()mengosongkan semua penimbal keluaran;
  • abstract void write(int oneByte)menulis 1 bait ke aliran keluaran;
  • void write(byte[] buffer)menulis tatasusunan bait ke aliran keluaran;
  • void write(byte[] buffer, int offset, int count)menulis julat bait kiraan daripada tatasusunan, bermula pada kedudukan mengimbangi.
Berikut adalah beberapa keturunan OutputStreamkelas tersebut:
  1. DataOutputStream. Strim output yang merangkumi kaedah untuk menulis jenis data Java standard.

    Kelas yang sangat mudah untuk menulis jenis data dan rentetan Java primitif. Anda mungkin akan memahami kod berikut walaupun tanpa penjelasan:

    import java.io.*;
    
    public class DataOutputStreamExample {
    
       public static void main(String[] args) throws IOException {
    
           DataOutputStream dos = new DataOutputStream(new FileOutputStream("testFile.txt"));
    
           dos.writeUTF("SomeString");
           dos.writeInt(22);
           dos.writeDouble(1.21323);
           dos.writeBoolean(true);
    
       }
    }

    Ia mempunyai kaedah berasingan untuk setiap jenis — writeDouble(), writeLong(), writeShort(), dan seterusnya.


  2. FileOutputStream. Kelas ini melaksanakan mekanisme untuk menghantar data ke fail pada cakera. Dengan cara ini, kami sudah menggunakannya dalam contoh terakhir. perasan tak? Kami menyerahkannya kepada DataOutputStream, yang bertindak sebagai 'pembungkus'.

  3. BufferedOutputStream. Aliran keluaran penimbal. Tidak ada yang rumit di sini. Tujuannya adalah serupa dengan BufferedInputStream(atau BufferedReader). Daripada bacaan berurutan biasa data, ia menulis data menggunakan penimbal 'kumulatif' khas. Penampan memungkinkan untuk mengurangkan bilangan kali sink data diakses, dengan itu meningkatkan prestasi.

    import java.io.*;
    
    public class DataOutputStreamExample {
    
         public static void main(String[] args) throws IOException {
    
               FileOutputStream outputStream = new FileOutputStream("D:/Users/Username/someFile.txt");
               BufferedOutputStream bufferedStream = new BufferedOutputStream(outputStream);
    
               String text = "I love Java!"; // We'll convert this string to a byte array and write it to a file
    
               byte[] buffer = text.getBytes();
    
               bufferedStream.write(buffer, 0, buffer.length);
         }
    }

    Sekali lagi, anda boleh bermain-main dengan kod ini sendiri dan mengesahkan bahawa ia akan berfungsi pada fail sebenar pada komputer anda.

Kami akan mempunyai pelajaran berasingan tentang FileInputStream, FileOutputStreamdan BuffreredInputStream, jadi ini adalah maklumat yang mencukupi untuk kenalan pertama. Itu sahaja! Kami harap anda memahami perbezaan antara antara muka dan kelas abstrak dan bersedia untuk menjawab sebarang soalan, walaupun soalan helah :)
Komen
  • Popular
  • Baru
  • Tua
Anda mesti log masuk untuk meninggalkan ulasan
Halaman ini tidak mempunyai sebarang ulasan lagi