CodeGym /จาวาบล็อก /สุ่ม /ความแตกต่างระหว่างคลาสนามธรรมและอินเทอร์เฟซ
John Squirrels
ระดับ
San Francisco

ความแตกต่างระหว่างคลาสนามธรรมและอินเทอร์เฟซ

เผยแพร่ในกลุ่ม
สวัสดี! ในบทเรียนนี้ เราจะพูดถึงความแตกต่างของคลาสนามธรรมจากอินเทอร์เฟซ และพิจารณาตัวอย่างบางส่วนที่มีคลาสนามธรรมทั่วไป ความแตกต่างระหว่างคลาสนามธรรมและอินเทอร์เฟซ - 1เราได้อุทิศบทเรียนแยกต่างหากสำหรับความแตกต่างระหว่างคลาสนามธรรมและอินเทอร์เฟซ เนื่องจากหัวข้อนี้สำคัญมาก คุณจะถูกถามเกี่ยวกับความแตกต่างระหว่างแนวคิดเหล่านี้ใน 90% ของการสัมภาษณ์ในอนาคต นั่นหมายความว่าคุณควรแน่ใจว่าคุณเข้าใจสิ่งที่คุณกำลังอ่านอยู่ และถ้าคุณไม่เข้าใจบางอย่าง ให้อ่านแหล่งข้อมูลเพิ่มเติม ดังนั้นเราจึงรู้ว่าคลาสนามธรรมคืออะไรและอินเทอร์เฟซคืออะไร ตอนนี้เราจะพูดถึงความแตกต่างของพวกเขา
  1. อินเทอร์เฟซอธิบายพฤติกรรมเท่านั้น มันไม่มีสถานะ แต่คลาสนามธรรมรวมถึงสถานะ: มันอธิบายทั้งสองอย่าง

    ตัวอย่างเช่น ใช้BirdคลาสนามธรรมและCanFlyอินเทอร์เฟซ:

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

    มาสร้างMockingJayคลาสนกและสืบทอดกัน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());
       }
    }
    

    อย่างที่คุณเห็น เราสามารถเข้าถึงสถานะของคลาสนามธรรมได้อย่างง่ายดาย — มันspeciesและageตัวแปร

    แต่ถ้าเราพยายามทำเช่นเดียวกันกับอินเทอร์เฟซ ภาพจะแตกต่างออกไป เราสามารถลองเพิ่มตัวแปรเข้าไปได้:

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

    เราไม่สามารถประกาศ ตัวแปร ส่วนตัวภายในอินเทอร์เฟซได้ ทำไม เนื่องจาก ตัวดัดแปลง ส่วนตัวถูกสร้างขึ้นเพื่อซ่อนการใช้งานจากผู้ใช้ และอินเทอร์เฟซไม่มีการใช้งานอยู่ภายใน: ไม่มีอะไรต้องซ่อน

    อินเทอร์เฟซอธิบายพฤติกรรมเท่านั้น ดังนั้นเราจึงไม่สามารถใช้ getters และ setters ภายในอินเทอร์เฟซได้ นี่คือธรรมชาติของอินเทอร์เฟซ: จำเป็นสำหรับการทำงานกับพฤติกรรม ไม่ใช่สถานะ

    Java 8 แนะนำวิธีการเริ่มต้นสำหรับอินเทอร์เฟซที่มีการนำไปใช้งาน คุณรู้เกี่ยวกับพวกเขาแล้ว ดังนั้นเราจะไม่พูดซ้ำ

  2. คลาสนามธรรมเชื่อมต่อและรวมคลาสที่เกี่ยวข้องอย่างใกล้ชิด ในเวลาเดียวกัน อินเทอร์เฟซเดียวสามารถนำไปใช้กับคลาสที่ไม่มีอะไรเหมือนกันเลย

    กลับไปที่ตัวอย่างของเรากับนก

    คลาสนามธรรม ของเราBirdจำเป็นสำหรับการสร้างนกที่มีพื้นฐานมาจากคลาสนั้น แค่นกและไม่มีอะไรอื่น! แน่นอนว่าจะมีนกชนิดต่างๆ

    ความแตกต่างระหว่างคลาสนามธรรมและอินเทอร์เฟซ - 2

    ด้วยCanFlyอินเทอร์เฟซ ทุกๆ คนดำเนินไปในแบบของตัวเอง มันอธิบายพฤติกรรม (การบิน) ที่เกี่ยวข้องกับชื่อของมันเท่านั้น สิ่งที่ไม่เกี่ยวข้องมากมาย 'บินได้'

    ความแตกต่างระหว่างคลาสนามธรรมและอินเทอร์เฟซ - 3

    หน่วยงานทั้ง 4 นี้ไม่เกี่ยวข้องกัน พวกเขาไม่ได้มีชีวิตทั้งหมดด้วยซ้ำ อย่างไรก็ตาม พวกเขาCanFlyทั้งหมด

    เราไม่สามารถอธิบายโดยใช้คลาสนามธรรมได้ พวกเขาไม่ได้แบ่งปันสถานะเดียวกันหรือฟิลด์ที่เหมือนกัน ในการระบุเครื่องบิน เราอาจต้องการฟิลด์สำหรับรุ่น ปีที่ผลิต และจำนวนผู้โดยสารสูงสุด สำหรับคาร์ลสัน เราต้องการทุ่งสำหรับขนมทั้งหมดที่เขากินในวันนี้ และรายชื่อเกมที่เขาจะเล่นกับน้องชายคนเล็กของเขา สำหรับยุง ...เอ่อ... ฉันไม่รู้ด้วยซ้ำว่า... อาจจะเป็น 'ระดับความรำคาญ'? :)

    ประเด็นคือเราไม่สามารถใช้คลาสนามธรรมเพื่ออธิบายได้ พวกเขาแตกต่างกันเกินไป แต่พวกมันมีพฤติกรรมร่วมกัน: พวกมันบินได้ อินเทอร์เฟซเหมาะสำหรับการอธิบายทุกสิ่งในโลกที่สามารถบิน ว่ายน้ำ กระโดด หรือแสดงพฤติกรรมอื่นๆ ได้

  3. คลาสสามารถใช้อินเทอร์เฟซได้มากเท่าที่คุณต้องการ แต่สามารถสืบทอดได้เพียงคลาสเดียวเท่านั้น

    เราได้กล่าวถึงเรื่องนี้มากกว่าหนึ่งครั้งแล้ว Java ไม่มีการสืบทอดหลายคลาส แต่รองรับการสืบทอดหลายอินเตอร์เฟส ประเด็นนี้เป็นไปตามส่วนก่อนหน้า: อินเทอร์เฟซเชื่อมต่อคลาสต่างๆ มากมายที่มักไม่มีอะไรเหมือนกัน ในขณะที่คลาสนามธรรมถูกสร้างขึ้นสำหรับกลุ่มของคลาสที่เกี่ยวข้องกันอย่างใกล้ชิด ดังนั้นจึงสมเหตุสมผลที่คุณจะสามารถสืบทอดคลาสดังกล่าวได้เพียงหนึ่งคลาสเท่านั้น คลาสนามธรรมอธิบายความสัมพันธ์แบบ 'is-a'

อินเทอร์เฟซมาตรฐาน: InputStream และ OutputStream

เราได้ศึกษาคลาสต่าง ๆ ที่รับผิดชอบอินพุตและเอาต์พุตสตรีมแล้ว ลองพิจารณาInputStreamและOutputStream. โดยทั่วไปแล้วสิ่งเหล่านี้ไม่ใช่อินเทอร์เฟซ แต่เป็นคลาสนามธรรมของแท้ทั้งหมด ตอนนี้คุณรู้แล้วว่ามันหมายถึงอะไร ดังนั้นการทำงานกับพวกมันจะง่ายขึ้นมาก :) InputStreamเป็นคลาสนามธรรมที่รับผิดชอบอินพุตไบต์ Java มีหลายคลาสที่สืบทอดInputStream. แต่ละคนได้รับการออกแบบเพื่อรับข้อมูลจากแหล่งต่างๆ เนื่องจากInputStreamเป็นพาเรนต์ จึงมีวิธีหลายวิธีที่ทำให้ทำงานกับสตรีมข้อมูลได้ง่าย ลูกหลานของแต่ละคนInputStreamมีวิธีการเหล่านี้:
  • int available()ส่งคืนจำนวนไบต์ที่สามารถอ่านได้
  • close()ปิดสตรีมอินพุต
  • int read()ส่งคืนการแสดงจำนวนเต็มของไบต์ถัดไปที่มีในสตรีม หากถึงจุดสิ้นสุดของสตรีม -1 จะถูกส่งกลับ
  • int read(byte[] buffer)พยายามอ่านไบต์ลงในบัฟเฟอร์ และส่งคืนจำนวนไบต์ที่อ่าน เมื่อถึงจุดสิ้นสุดของไฟล์ จะส่งกลับ -1;
  • int read(byte[] buffer, int byteOffset, int byteCount)เขียนส่วนหนึ่งของบล็อกของไบต์ ใช้เมื่ออาร์เรย์ไบต์อาจไม่เต็ม เมื่อถึงจุดสิ้นสุดของไฟล์ จะส่งกลับ -1;
  • long skip(long byteCount)ข้าม byteCount ไบต์ในสตรีมอินพุต และส่งคืนจำนวนไบต์ที่ถูกละเว้น
ฉันขอแนะนำให้ คุณศึกษารายการวิธีการทั้งหมด เด็กเรียนมีสิบกว่าคนจริงๆ ตัวอย่างเช่น นี่คือบางส่วน:
  1. FileInputStream: ชนิดที่พบบ่อยที่สุดของInputStream. ใช้เพื่ออ่านข้อมูลจากไฟล์
  2. StringBufferInputStream: อีกประเภทที่เป็นประโยชน์ของInputStream. มันแปลงสตริงเป็นInputStream;
  3. BufferedInputStream: สตรีมอินพุตบัฟเฟอร์ ใช้บ่อยที่สุดเพื่อเพิ่มประสิทธิภาพ
จำตอนที่เราไปBufferedReaderบอกว่าไม่ต้องใช้ได้ไหม เมื่อเราเขียน:

BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))
…คุณไม่จำเป็นต้องใช้BufferedReader: An InputStreamReadercan do the job. แต่BufferedReaderปรับปรุงประสิทธิภาพและยังสามารถอ่านข้อมูลทั้งบรรทัดแทนที่จะเป็นอักขระแต่ละตัว สิ่งเดียวกันนี้ใช้กับBufferedInputStream! คลาสจะรวบรวมข้อมูลอินพุตในบัฟเฟอร์พิเศษโดยไม่ต้องเข้าถึงอุปกรณ์อินพุตตลอดเวลา ลองพิจารณาตัวอย่าง:

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();
       }
   }
}
ในตัวอย่างนี้ เราอ่านข้อมูลจากไฟล์ที่อยู่ในคอมพิวเตอร์ที่ ' D:/Users/UserName/someFile.txt ' เราสร้างวัตถุ 2 ชิ้น — a FileInputStreamและ a BufferedInputStreamที่ 'ห่อหุ้ม' จากนั้นเราจะอ่านไบต์จากไฟล์และแปลงเป็นอักขระ และเราทำจนกว่าไฟล์จะสิ้นสุด อย่างที่คุณเห็นไม่มีอะไรซับซ้อนที่นี่ คุณสามารถคัดลอกรหัสนี้และรันบนไฟล์จริงบนคอมพิวเตอร์ของคุณ :) OutputStreamคลาสนี้เป็นคลาสนามธรรมที่แสดงถึงเอาต์พุตสตรีมของไบต์ ดังที่คุณทราบแล้ว สิ่งนี้ตรงกันข้ามกับไฟล์InputStream. ไม่มีหน้าที่ในการอ่านข้อมูลจากที่ใดที่หนึ่ง แต่รับผิดชอบในการส่งข้อมูลที่ใดที่หนึ่ง เช่นInputStreamคลาสนามธรรมนี้ให้ชุดวิธีการที่สะดวกแก่ลูกหลานทั้งหมด:
  • void close()ปิดสตรีมเอาต์พุต
  • void flush()ล้างบัฟเฟอร์เอาต์พุตทั้งหมด
  • abstract void write(int oneByte)เขียน 1 ไบต์ไปยังสตรีมเอาต์พุต
  • void write(byte[] buffer)เขียนอาร์เรย์ไบต์ไปยังสตรีมเอาต์พุต
  • void write(byte[] buffer, int offset, int count)เขียนช่วงจำนวนไบต์จากอาร์เรย์ เริ่มต้นที่ตำแหน่งออฟเซ็ต
นี่คือลูกหลานของOutputStreamชั้นเรียนบางส่วน:
  1. DataOutputStream. เอาต์พุตสตรีมที่มีเมธอดสำหรับการเขียนชนิดข้อมูลมาตรฐาน Java

    คลาสที่ง่ายมากสำหรับการเขียนประเภทข้อมูลและสตริงดั้งเดิมของ Java คุณอาจจะเข้าใจรหัสต่อไปนี้แม้ว่าจะไม่มีคำอธิบายก็ตาม:

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

    มีวิธีการแยกสำหรับแต่ละประเภท — writeDouble(), writeLong(), writeShort(), และอื่นๆ


  2. FileOutputStream. คลาสนี้ใช้กลไกในการส่งข้อมูลไปยังไฟล์บนดิสก์ อย่างไรก็ตาม เราได้ใช้มันไปแล้วในตัวอย่างที่แล้ว คุณสังเกตเห็นหรือไม่? เราส่งต่อไปยัง DataOutputStream ซึ่งทำหน้าที่เป็น 'wrapper'

  3. BufferedOutputStream. กระแสเอาต์พุตบัฟเฟอร์ นอกจากนี้ยังไม่มีอะไรซับซ้อนที่นี่ จุดประสงค์ของมันคล้ายกับBufferedInputStream(หรือBufferedReader) แทนที่จะอ่านข้อมูลตามลำดับตามปกติ จะเขียนข้อมูลโดยใช้บัฟเฟอร์ 'สะสม' แบบพิเศษ บัฟเฟอร์ทำให้สามารถลดจำนวนครั้งที่เข้าถึงอ่างข้อมูล ซึ่งจะเป็นการเพิ่มประสิทธิภาพ

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

    อีกครั้ง คุณสามารถลองใช้โค้ดนี้ด้วยตัวเองและตรวจสอบว่าโค้ดนี้ใช้ได้กับไฟล์จริงในคอมพิวเตอร์ของคุณ

เราจะมีบทเรียนแยกต่างหากเกี่ยวกับFileInputStreamและFileOutputStreamดังนั้นBuffreredInputStreamนี่จึงเป็นข้อมูลที่เพียงพอสำหรับการทำความรู้จักกันครั้งแรก แค่นั้นแหละ! เราหวังว่าคุณจะเข้าใจความแตกต่างระหว่างอินเทอร์เฟซและคลาสนามธรรม และพร้อมที่จะตอบคำถามใด ๆ แม้กระทั่งคำถามลวง :)
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION