JavaRush /จาวาบล็อก /Random-TH /อินเทอร์เฟซใน Java

อินเทอร์เฟซใน Java

เผยแพร่ในกลุ่ม
สวัสดี! วันนี้เราจะพูดถึงแนวคิดที่สำคัญใน Java - อินเทอร์เฟซ คำนี้คงจะคุ้นเคยสำหรับคุณ ตัวอย่างเช่น โปรแกรมคอมพิวเตอร์และเกมส่วนใหญ่มีอินเทอร์เฟซ ในความหมายกว้างๆ อินเทอร์เฟซคือ "รีโมทคอนโทรล" ประเภทหนึ่งที่เชื่อมโยงทั้งสองฝ่ายที่มีปฏิสัมพันธ์ระหว่างกัน ตัวอย่างง่ายๆ ของอินเทอร์เฟซจากชีวิตประจำวันคือรีโมทคอนโทรลของทีวี โดยจะเชื่อมต่อวัตถุสองชิ้น บุคคลกับทีวี และทำงานที่แตกต่างกัน: เพิ่มหรือลดระดับเสียง เปลี่ยนช่อง เปิดหรือปิดทีวี ด้านหนึ่ง (บุคคล) จำเป็นต้องเข้าถึงอินเทอร์เฟซ (กดปุ่มรีโมทคอนโทรล) เพื่อให้อีกด้านหนึ่งดำเนินการ เช่นให้ทีวีเปลี่ยนช่องไปช่องถัดไป ในกรณีนี้ผู้ใช้ไม่จำเป็นต้องทราบอุปกรณ์ของทีวีและวิธีการเปลี่ยนช่องภายใน เหตุใดจึงจำเป็นต้องมีอินเทอร์เฟซใน Java - 1ผู้ใช้ทุกคนที่มีสิทธิ์เข้าถึงคืออินเทอร์เฟซ ภารกิจหลักคือการได้รับผลลัพธ์ที่ต้องการ สิ่งนี้เกี่ยวข้องกับการเขียนโปรแกรมและ Java อย่างไร? โดยตรง :) การสร้างอินเทอร์เฟซนั้นคล้ายกับการสร้างคลาสปกติมาก แต่แทนที่จะเป็นคำที่classเราระบุคำว่าinterface. มาดูอินเทอร์เฟซ Java ที่ง่ายที่สุดแล้วดูว่ามันทำงานอย่างไรและจำเป็นสำหรับอะไร:
public interface Swimmable  {

     public void swim();
}
เราสร้างอินเทอร์เฟซSwimmableที่สามารถว่ายน้ำได้ นี่คือสิ่งที่คล้ายกับรีโมตคอนโทรลของเราซึ่งมี "ปุ่ม" เพียงปุ่มเดียว: วิธีการswim() คือ "ว่ายน้ำ" เราจะใช้ “ รีโมทคอนโทรล ” นี้ได้อย่างไร? เพื่อจุดประสงค์นี้วิธีการคือ จำเป็นต้องใช้ปุ่มบนรีโมทคอนโทรลของเรา หากต้องการใช้อินเทอร์เฟซ วิธีการของมันจะต้องได้รับการปรับใช้โดยคลาสบางคลาสของโปรแกรมของเรา มาดูชั้นเรียนที่มีวัตถุตรงกับคำอธิบายว่า "ว่ายน้ำได้" ตัวอย่างเช่น คลาสเป็ดมีความเหมาะสมDuck:
public class Duck implements Swimmable {

    public void swim() {
        System.out.println("Duck, swim!");
    }

    public static void main(String[] args) {

        Duck duck = new Duck();
        duck.swim();
    }
}
เราเห็นอะไรที่นี่? คลาสDuckเชื่อมโยงกับอินเทอร์เฟซโดยSwimmableใช้คีย์เวิร์ด implementsหากคุณจำได้ เราใช้กลไกที่คล้ายกันเพื่อเชื่อมโยงสองคลาสในการสืบทอด มีเพียงคำว่า " ขยาย " เท่านั้น “ public class Duck implements Swimmable” สามารถแปลตามตัวอักษรเพื่อความชัดเจน: “คลาสสาธารณะDuckใช้อินเทอร์เฟซSwimmable” ซึ่งหมายความว่าคลาสที่เกี่ยวข้องกับอินเทอร์เฟซจะต้องใช้วิธีการทั้งหมดของมัน โปรดทราบ:ในชั้นเรียนของเรามี method อยู่Duckเช่นเดียวกับใน interface และภายในนั้นมีตรรกะบางอย่าง นี่เป็นข้อกำหนดบังคับ หากเราเพิ่งเขียน “ ” และไม่ได้สร้างเมธอดในคลาสคอมไพเลอร์ก็จะแจ้งข้อผิดพลาดให้เราทราบ: Duck ไม่ใช่นามธรรมและไม่ได้แทนที่เมธอดนามธรรม swim() ใน Swimmable ทำไมสิ่งนี้ถึงเกิดขึ้น? หากเราอธิบายข้อผิดพลาดโดยใช้ตัวอย่างทีวีปรากฎว่าเราให้รีโมทคอนโทรลแก่บุคคลด้วยปุ่ม "เปลี่ยนช่อง" จากทีวีที่ไม่รู้วิธีเปลี่ยนช่อง เมื่อถึงจุดนี้ให้กดปุ่มเท่าที่คุณต้องการก็จะไม่มีอะไรทำงาน รีโมทคอนโทรลเองไม่เปลี่ยนช่อง: เพียงส่งสัญญาณไปยังทีวีซึ่งภายในนั้นมีกระบวนการที่ซับซ้อนในการเปลี่ยนช่อง เช่นเดียวกับเป็ดของเรา: มันจะต้องว่ายน้ำได้จึงจะสามารถเข้าถึงได้โดยใช้อินเทอร์เฟซ. หากเธอไม่ทราบวิธีการทำเช่นนี้ อินเทอร์เฟซจะไม่เชื่อมต่อทั้งสองด้าน - บุคคลและโปรแกรม บุคคลจะไม่สามารถใช้วิธีการเพื่อทำให้วัตถุภายในโปรแกรมลอยได้ ตอนนี้คุณได้เห็นชัดเจนยิ่งขึ้นว่าอินเทอร์เฟซมีไว้เพื่ออะไร อินเทอร์เฟซอธิบายลักษณะการทำงานที่คลาสที่ใช้อินเทอร์เฟซนั้นต้องมี “พฤติกรรม” คือชุดของวิธีการ หากเราต้องการสร้างผู้ส่งสารหลายราย วิธีที่ง่ายที่สุดในการทำเช่นนี้คือการสร้างอินเทอร์เฟซ ผู้ส่งสารคนใดสามารถทำอะไรได้บ้าง? รับและส่งข้อความในรูปแบบที่เรียบง่าย Swimmableswim()public class Duck implements Swimmableswim()DuckSwimmableSwimmableswim()DuckMessenger
public interface Messenger{

     public void sendMessage();

     public void getMessage();
}
และตอนนี้เราสามารถสร้างคลาส Messenger ของเราได้โดยใช้อินเทอร์เฟซนี้ คอมไพเลอร์จะ "บังคับ" ให้เรานำไปใช้ภายในคลาส โทรเลข:
public class Telegram implements Messenger {

    public void sendMessage() {

        System.out.println("Sending a message to Telegram!");
    }

     public void getMessage() {
         System.out.println("Reading the message in Telegram!");
     }
}
วอทส์แอพพ์:
public class WhatsApp implements Messenger {

    public void sendMessage() {

        System.out.println("Sending a WhatsApp message!");
    }

     public void getMessage() {
         System.out.println("Reading a WhatsApp message!");
     }
}
ไวเบอร์:
public class Viber implements Messenger {

    public void sendMessage() {

        System.out.println("Sending a message to Viber!");
    }

     public void getMessage() {
         System.out.println("Reading a message in Viber!");
     }
}
สิ่งนี้ให้ประโยชน์อะไรบ้าง? สิ่งสำคัญที่สุดคือการมีเพศสัมพันธ์แบบหลวม ลองจินตนาการว่าเรากำลังออกแบบโปรแกรมที่เราจะรวบรวมข้อมูลลูกค้า ชั้นเรียนClientจะต้องมีช่องที่ระบุว่า Messenger ตัวใดที่ไคลเอ็นต์ใช้ หากไม่มีอินเทอร์เฟซก็จะดูแปลก:
public class Client {

    private WhatsApp whatsApp;
    private Telegram telegram;
    private Viber viber;
}
เราสร้างช่องข้อมูลไว้ 3 ช่อง แต่ลูกค้าสามารถมี Messenger เพียงช่องเดียวได้อย่างง่ายดาย เราแค่ไม่รู้ว่าอันไหน และเพื่อไม่ให้ถูกทิ้งไว้โดยไม่มีการสื่อสารกับลูกค้า คุณต้อง "ผลักดัน" ตัวเลือกที่เป็นไปได้ทั้งหมดเข้ามาในชั้นเรียน ปรากฎว่ามีหนึ่งหรือสองคนอยู่ที่นั่นเสมอnullและไม่จำเป็นเลยเพื่อให้โปรแกรมทำงานได้ ควรใช้อินเทอร์เฟซของเราแทน:
public class Client {

    private Messenger messenger;
}
นี่คือตัวอย่างของ “ข้อต่อหลวม”! แทนที่จะระบุคลาส Messenger เฉพาะใน class Clientเราเพียงแต่ระบุว่าไคลเอ็นต์มี Messenger อันไหนจะถูกกำหนดในระหว่างหลักสูตร แต่ทำไมเราถึงต้องการอินเทอร์เฟซสำหรับสิ่งนี้? ทำไมพวกเขาถึงเพิ่มเข้าไปในภาษาเลย? คำถามดีและถูกต้อง! ผลลัพธ์เดียวกันนี้สามารถทำได้โดยใช้มรดกธรรมดาใช่ไหม? คลาสMessengerคือคลาสพาเรนต์ และและViberคือทายาท แท้จริงแล้วมันเป็นไปได้ที่จะทำเช่นนั้น แต่มีสิ่งหนึ่งที่จับได้ ดังที่คุณทราบแล้วว่า Java ไม่มีการสืบทอดหลายรายการ แต่มีการใช้งานอินเทอร์เฟซหลายอย่าง คลาสสามารถใช้อินเทอร์เฟซได้มากเท่าที่ต้องการ ลองนึกภาพว่าเรามีคลาสที่มีฟิลด์- แอปพลิเคชันที่ติดตั้งบนสมาร์ทโฟน TelegramWhatsAppSmartphoneApplication
public class Smartphone {

    private Application application;
}
แน่นอนว่าแอปพลิเคชั่นและผู้ส่งสารนั้นคล้ายกัน แต่ก็ยังเป็นสิ่งที่แตกต่างกัน Messenger เป็นได้ทั้งมือถือและเดสก์ท็อป ในขณะที่ Application เป็นแอปพลิเคชั่นมือถือ ดังนั้นหากเราใช้ inheritance เราจะไม่สามารถเพิ่ม object Telegramให้กับ class Smartphoneได้ ท้ายที่สุดแล้ว คลาสTelegramไม่สามารถสืบทอดจากApplicationและจากMessenger! และเราได้จัดการสืบทอดมันมาจากMessengerและเพิ่มลงในคลาสในรูปแบบClientนี้ แต่คลาสTelegramสามารถใช้ทั้งสองอินเทอร์เฟซได้อย่างง่ายดาย! ดังนั้นในคลาส เราจึง สามารถClientImplement วัตถุTelegramเป็นMessengerและในคลาสSmartphoneเป็น Applicationต่อไปนี้เป็นวิธีดำเนินการ:
public class Telegram implements Application, Messenger {

    //...methods
}

public class Client {

    private Messenger messenger;

    public Client() {
        this.messenger = new Telegram();
    }
}


public class Smartphone {

    private Application application;

    public Smartphone() {
        this.application = new Telegram();
    }
}
ตอนนี้เราสามารถใช้คลาสTelegramได้ตามต้องการ ที่ไหนสักแห่งเขาจะแสดงในบทบาทของApplicationที่ไหนสักแห่งในบทบาทMessengerของ คุณอาจสังเกตเห็นแล้วว่าวิธีการในอินเทอร์เฟซนั้น "ว่างเปล่า" เสมอนั่นคือไม่มีการใช้งาน เหตุผลง่ายๆ ก็คือ อินเทอร์เฟซอธิบายพฤติกรรม ไม่ใช่นำไปใช้ “ออบเจ็กต์ทั้งหมดของคลาสที่ใช้อินเทอร์เฟซSwimmableจะต้องสามารถลอยได้” นั่นคือทั้งหมดที่อินเทอร์เฟซบอกเรา ปลา เป็ด หรือม้าจะว่าย น้ำได้อย่างไร มีคำถามสำหรับคลาสFishและไม่ใช่สำหรับอินเทอร์เฟซ เช่นเดียวกับการเปลี่ยนช่องเป็นหน้าที่ของทีวี รีโมทเพียงกดปุ่มให้คุณทำ อย่างไรก็ตาม Java8 มีการเพิ่มเติมที่น่าสนใจ - วิธีการเริ่มต้น ตัวอย่างเช่น อินเทอร์เฟซของคุณมี 10 วิธี มี 9 รายการที่มีการนำไปใช้ที่แตกต่างกันในคลาสที่แตกต่างกัน แต่มีรายการหนึ่งถูกนำไปใช้เหมือนกันในทุกคลาส ก่อนหน้านี้ก่อนการเปิดตัว Java8 วิธีการภายในอินเทอร์เฟซไม่มีการนำไปใช้เลย: คอมไพเลอร์แสดงข้อผิดพลาดทันที ตอนนี้คุณสามารถทำเช่นนี้: DuckHorse
public interface Swimmable {

   public default void swim() {
       System.out.println("Swim!");
   }

   public void eat();

   public void run();
}
การใช้คำหลักdefaultเราได้สร้างวิธีการในส่วนต่อประสานที่มีการใช้งานเริ่มต้น เราจะต้องนำ อีกสองวิธี ไปใช้ eat()และrun()ตัวเราเองในทุกคลาสที่จะนำไปSwimmableใช้ ไม่จำเป็นต้องทำเช่นนี้ กับวิธีการswim(): การใช้งานจะเหมือนกันในทุกคลาส อย่างไรก็ตาม คุณได้พบอินเทอร์เฟซมากกว่าหนึ่งครั้งในงานที่ผ่านมา แม้ว่าคุณจะไม่ได้สังเกตด้วยตัวเองก็ตาม :) นี่คือตัวอย่างที่ชัดเจน: เหตุใดเราจึงต้องมีอินเทอร์เฟซใน Java - 2คุณทำงานกับอินเทอร์เฟซListและSet! แม่นยำยิ่งขึ้นด้วยการใช้งาน - ArrayList, LinkedListและHashSetอื่น ๆ แผนภาพเดียวกันนี้แสดงตัวอย่างเมื่อคลาสหนึ่งใช้งานหลายอินเทอร์เฟซพร้อมกัน ตัวอย่างเช่นLinkedListใช้อินเทอร์เฟซListและDeque(คิวสองด้าน) คุณยังคุ้นเคยกับอินเทอร์เฟซMapหรือมากกว่านั้นด้วยการใช้งานHashMap- อย่างไรก็ตามในแผนภาพนี้คุณสามารถเห็นคุณลักษณะหนึ่ง: อินเทอร์เฟซสามารถสืบทอดจากกันและกันได้ อินเทอร์เฟซSortedMapสืบทอดมาจากMapและDequeสืบทอดมาจากQueueคิว นี่เป็นสิ่งจำเป็นถ้าคุณต้องการแสดงการเชื่อมต่อระหว่างอินเทอร์เฟซ แต่อินเทอร์เฟซหนึ่งเป็นเวอร์ชันขยายของอีกอินเทอร์เฟซหนึ่ง ลองดูตัวอย่างด้วยอินเทอร์เฟซQueue- คิว เรายังไม่ได้ดูคอลเลกชันต่างๆQueueแต่ค่อนข้างเรียบง่ายและจัดเรียงเหมือนแถวปกติในร้านค้า คุณสามารถเพิ่มองค์ประกอบที่ส่วนท้ายของคิวเท่านั้น และนำองค์ประกอบเหล่านั้นออกจากจุดเริ่มต้นเท่านั้น ในขั้นตอนหนึ่ง นักพัฒนาจำเป็นต้องมีเวอร์ชันขยายของคิวเพื่อให้สามารถเพิ่มและรับองค์ประกอบจากทั้งสองฝ่ายได้ นี่คือวิธีการสร้างอินเทอร์เฟซDeque- คิวแบบสองทาง ประกอบด้วยวิธีการทั้งหมดของคิวปกติ เนื่องจากเป็น "พาเรนต์" ของคิวแบบสองทาง แต่มีการเพิ่มวิธีการใหม่แล้ว
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION