JavaRush /Java Blogu /Random-AZ /Abstrakt siniflər və interfeyslər arasındakı fərq

Abstrakt siniflər və interfeyslər arasındakı fərq

Qrupda dərc edilmişdir
Salam! Bu mühazirədə biz abstrakt siniflərin interfeyslərdən necə fərqləndiyi haqqında danışacağıq və ümumi abstrakt siniflərlə nümunələrə baxacağıq. Abstrakt siniflər və interfeyslər arasındakı fərq - 1Mövzu çox vacib olduğu üçün mücərrəd sinif və interfeys arasındakı fərqlərə ayrıca mühazirə həsr etdik. Gələcək müsahibələrin 90%-də sizdən bu anlayışlar arasındakı fərq barədə soruşulacaq. Odur ki, oxuduqlarınızı mütləq anlayın, nəyisə tam başa düşmürsünüzsə, əlavə mənbələri oxuyun. Beləliklə, biz abstrakt sinifin nə olduğunu və interfeysin nə olduğunu bilirik. İndi onların fərqlərinə keçək.
  1. İnterfeys yalnız davranışı təsvir edir. Onun taleyi yoxdur. Lakin mücərrəd sinfin bir vəziyyəti var: o, hər ikisini təsvir edir.

    BirdNümunə olaraq abstrakt sinif və interfeysi götürək Flyable:

    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;
       }
    }

    Gəlin bir quş sinfi Mockingjay(mockingjay) yaradaq və ondan miras alaq Bird:

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

    Gördüyünüz kimi, biz mücərrəd sinfin vəziyyətinə - onun dəyişənlərinə species(növ) və age(yaş) asanlıqla daxil ola bilərik.

    Ancaq interfeyslə eyni şeyi etməyə çalışsaq, şəkil fərqli olacaq. Biz ona dəyişənlər əlavə etməyə cəhd edə bilərik:

    public interface Flyable {
    
       String species = new String();
       int age = 10;
    
       public void fly();
    }
    
    public interface Flyable {
    
       private String species = new String(); // error
       private int age = 10; // also an error
    
       public void fly();
    }

    Biz hətta interfeys daxilində şəxsi dəyişənlər yarada bilməyəcəyik . Niyə? Çünki özəl modifikator tətbiqi istifadəçidən gizlətmək üçün yaradılmışdır. Ancaq interfeys daxilində heç bir tətbiq yoxdur: orada gizlənə biləcək heç bir şey yoxdur.

    İnterfeys yalnız davranışı təsvir edir. Müvafiq olaraq, biz interfeys daxilində alıcıları və tənzimləyiciləri həyata keçirə bilməyəcəyik. Bu, interfeysin xarakteridir: o, vəziyyətlə deyil, davranışla məşğul olmaq üçün nəzərdə tutulub.

    Java8 tətbiqi olan standart interfeys üsullarını təqdim etdi. Siz artıq onlar haqqında bilirsiniz, ona görə də onları təkrar etməyəcəyik.

  2. Mücərrəd sinif çox sıx əlaqədə olan sinifləri əlaqələndirir və birləşdirir. Eyni zamanda, eyni interfeys ümumiyyətlə heç bir ortaqlığı olmayan siniflər tərəfindən həyata keçirilə bilər.

    Quşlarla bağlı nümunəmizə qayıdaq.

    BirdOnun əsasında quşlar yaratmaq üçün abstrakt sinifimiz lazımdır. Yalnız quşlar və başqa heç kim! Təbii ki, fərqli olacaqlar.

    Abstrakt siniflər və interfeyslər arasındakı fərq - 2

    İnterfeys ilə Flyablehər şey fərqlidir. O, yalnız adına uyğun davranışı təsvir edir - "uçmaq". “Uçan”, “uça bilən” anlayışına bir-biri ilə əlaqəsi olmayan çoxlu obyektlər daxildir.

    Abstrakt siniflər və interfeyslər arasındakı fərq - 3

    Bu 4 varlıq heç bir şəkildə bir-biri ilə əlaqəli deyil. Nə deyim, heç də hamısı canlı deyil. Bununla belə, onların hamısı Flyableuçuş qabiliyyətinə malikdir.

    Mücərrəd sinifdən istifadə edərək onları təsvir edə bilməyəcəyik. Onların ümumi dövləti və ya eyni sahələri yoxdur. Təyyarəni xarakterizə etmək üçün yəqin ki, “model”, “istehsal ili” və “maksimum sərnişin sayı” sahələrinə ehtiyacımız olacaq. Carlson üçün bu gün yediyi bütün şirniyyatlar üçün sahələr və Uşaqla oynayacağı oyunların siyahısı var. Bir ağcaqanad üçün ... uh-uh ... biz hətta bilmirik ... Bəlkə "qıcıqlanma səviyyəsi"? :)

    Əsas odur ki, biz onları abstrakt sinifdən istifadə edərək təsvir edə bilmərik. Onlar çox fərqlidirlər. Ancaq ümumi bir davranış var: uça bilərlər. İnterfeys dünyada uça, üzə, tullanmaya və ya başqa davranışlara malik olan hər şeyi təsvir etmək üçün idealdır.

  3. Siniflər istədikləri qədər interfeys həyata keçirə bilər, lakin onlar yalnız bir sinifdən miras ala bilərlər.

    Bu barədə artıq bir dəfədən çox danışmışıq. Java-da çoxsaylı miras yoxdur, lakin çoxlu tətbiqetmə var. Bu məqam qismən əvvəlkindən irəli gəlir: interfeys çox vaxt ortaq heç nəyi olmayan çoxlu müxtəlif sinifləri birləşdirir və bir-birinə çox yaxın olan siniflər qrupu üçün mücərrəd sinif yaradılır. Buna görə də, yalnız bir belə sinifdən miras ala biləcəyiniz məntiqlidir. Mücərrəd sinif "bir" əlaqəsini təsvir edir.

Standart InputStream & OutputStream İnterfeysləri

Biz artıq axın girişi və çıxışı üçün məsul olan müxtəlif siniflərdən keçmişik. Gəlin baxaq InputStreamOutputStream. Ümumiyyətlə, bunlar interfeys deyil, real abstrakt siniflərdir. İndi onların nə olduğunu bilirsiniz, ona görə də onlarla işləmək çox asan olacaq :) InputStream- bu bayt daxilinə cavabdeh olan mücərrəd sinifdir. Java-dan miras qalan bir sıra siniflərə malikdir InputStream. Onların hər biri müxtəlif mənbələrdən məlumat almaq üçün konfiqurasiya edilmişdir. InputStreamO, valideyn olduğu üçün məlumat axınları ilə rahat işləmək üçün bir neçə üsul təqdim edir. Hər bir uşağın bu üsulları var InputStream:
  • int available()oxumaq üçün mövcud baytların sayını qaytarır;
  • close()giriş mənbəyini bağlayır;
  • int read()axındakı növbəti mövcud baytın tam təsvirini qaytarır. Əgər axın sonuna çatarsa, -1 rəqəmi qaytarılacaq;
  • int read(byte[] buffer)baytları buferə oxumağa çalışır, oxunan baytların sayını qaytarır. Faylın sonuna çatdıqda -1 qaytarır;
  • int read(byte[] buffer, int byteOffset, int byteCount)bayt blokunun bir hissəsini oxuyur. Məlumat blokunun tam doldurulmaması ehtimalı olduqda istifadə olunur. Faylın sonuna çatdıqda -1 qaytarır;
  • long skip(long byteCount)skips byteCount, bir bayt giriş, nəzərə alınmayan baytların sayını qaytarır.
Metodların tam siyahısını öyrənməyi məsləhət görürəm . Əslində ondan çox davamçı sinif var. Budur bir neçə nümunə:
  1. FileInputStream: ən ümumi növü InputStream. Fayldan məlumatı oxumaq üçün istifadə olunur;
  2. StringBufferInputStream: başqa faydalı növ InputStream. O, sətri giriş məlumat axınına çevirir InputStream;
  3. BufferedInputStream: buferli giriş axını. Ən çox səmərəliliyi artırmaq üçün istifadə olunur.
BufferedReaderYanımızdan keçib istifadə etməli olduğumuzu dediyimizi xatırlayırsınızmı ? Yazdığımız zaman:
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))
... BufferedReaderistifadə etməyə ehtiyac yoxdur: InputStreamReaderişi görəcək. Lakin BufferedReadero, bunu daha səmərəli edir və üstəlik, məlumatları ayrı-ayrı simvollarla deyil, bütün sətirlərdə oxuya bilir. Hər şey BufferedInputStreameynidir! Sinif giriş məlumatlarını daim daxiletmə qurğusuna daxil olmadan xüsusi buferdə toplayır. Bir misala baxaq:
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 was read" + c);
           }
       } catch(Exception e) {

           e.printStackTrace();

       } finally {

           inputStream.close();
           buffer.close();
       }
   }
}
Bu nümunədə biz kompüterdə "D:/Users/UserName/someFile.txt" ünvanında yerləşən fayldan məlumatları oxuyuruq . Biz 2 obyekt yaradırıq - FileInputStreamBufferedInputStreamonun "sarğı" kimi. Bundan sonra fayldan baytları oxuyuruq və onları simvollara çeviririk. Və fayl bitənə qədər. Gördüyünüz kimi, burada mürəkkəb bir şey yoxdur. Siz bu kodu kopyalayıb kompüterinizdə saxlanılan bəzi real faylda işlədə bilərsiniz :) OutputStreamSinif bayt axını çıxışını təyin edən mücərrəd sinifdir. Artıq başa düşdüyünüz kimi, bu, 'a'nın antipodudur InputStream. O, məlumatların haradan oxunacağına deyil, hara göndəriləcəyinə görə məsuliyyət daşıyır . Məsələn InputStream, bu mücərrəd sinif bütün nəsillərə rahat iş üçün bir qrup üsul təqdim edir:
  • int close()çıxış axını bağlayır;
  • void flush()bütün çıxış tamponlarını təmizləyir;
  • abstract void write (int oneByte)çıxış axınına 1 bayt yazır;
  • void write (byte[] buffer)çıxış axınına bayt massivi yazır;
  • void write (byte[] buffer, int offset, int count)mövqe ofsetindən başlayaraq massivdən bir sıra bayt sayı yazır.
Budur sinifin nəslindən bəziləri OutputStream:
  1. DataOutputStream. Standart Java məlumat növlərinin yazılması üsullarını ehtiva edən çıxış axını.

    Primitiv Java növləri və sətirlərinin yazılması üçün çox sadə sinif. Şübhəsiz ki, yazılı kodu izah etmədən də başa düşəcəksiniz:

    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);
    
       }
    }

    Onun hər bir növ üçün ayrıca üsulları var - writeDouble(), writeLong(), writeShort()və s.

  2. Sinif FileOutputStream . Diskdəki fayla verilənlərin göndərilməsi mexanizmini həyata keçirir. Yeri gəlmişkən, biz bundan əvvəlki nümunədə artıq istifadə etmişik, fikir vermisiniz? Biz onu “sarğı” kimi çıxış edən DataOutputStream-in içərisinə keçirdik.

  3. BufferedOutputStream. Buferli çıxış axını. BufferedInputStreamMürəkkəb bir şey də yoxdur, mahiyyət (və ya 'a) ilə eynidir BufferedReader. Adi ardıcıl məlumat qeydinin əvəzinə xüsusi "saxlama" buferi vasitəsilə qeyd istifadə olunur. Buferdən istifadə etməklə siz məlumat təyinatına gediş-gəlişlərin sayını azalda və bununla da səmərəliliyi artıra bilərsiniz.

    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 will convert this string into an array of bytes and write it to a file
    
           byte[] buffer = text.getBytes();
    
           bufferedStream.write(buffer, 0, buffer.length);
           bufferedStream.close();
       }
    }

    Yenə də bu kodla özünüz "oynaya" və onun kompüterinizdəki real fayllarda necə işləyəcəyini yoxlaya bilərsiniz.

Siz həmçinin “ InputStreamGiriş /Çıxış SistemiOutputStream ” materialında varislər haqqında oxuya bilərsiniz . Oh , bizim də ayrıca mühazirəmiz olacaq, ona görə də ilk tanışlıq üçün onlar haqqında kifayət qədər məlumat var. Hamısı budur! Ümid edirik ki, siz interfeyslər və abstrakt siniflər arasındakı fərqləri yaxşı başa düşürsünüz və istənilən suala, hətta çətin suala belə cavab verməyə hazırsınız :) FileInputStreamFileOutputStreamBufferedInputStream
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION