JavaRush /จาวาบล็อก /Random-TH /คอฟฟี่เบรค #140. คลาสนามธรรมและอินเทอร์เฟซใน Java

คอฟฟี่เบรค #140. คลาสนามธรรมและอินเทอร์เฟซใน Java

เผยแพร่ในกลุ่ม
ที่มา: InfoWorld วันนี้คุณจะได้เรียนรู้ว่าในกรณีใดที่นักพัฒนาควรใช้คลาสนามธรรม และในกรณีใดคืออินเทอร์เฟซ นอกจากนี้เรายังจะระบุความแตกต่างระหว่างองค์ประกอบเหล่านี้ของภาษา Java และวิธีการใช้ในโปรแกรม คอฟฟี่เบรค #140.  คลาสนามธรรมและอินเทอร์เฟซใน Java - 1คลาสนามธรรมและอินเทอร์เฟซนั้นค่อนข้างพบได้ทั่วไปในโค้ด Java และแม้แต่ใน Java Development Kit (JDK) เอง แต่ละองค์ประกอบเหล่านี้มีจุดประสงค์ที่แตกต่างกัน:
  • อินเทอร์เฟซคือโครงสร้างในภาษา Java ที่ช่วยนำเมธอดนามธรรมและค่าคงที่แบบคงที่ไปใช้
  • คลาสนามธรรมนั้นคล้ายคลึงกับคลาสปกติ ยกเว้นว่าสามารถรวมวิธีนามธรรมได้ นั่นคือ วิธีการที่ไม่มีเนื้อหา ไม่สามารถสร้างคลาสนามธรรมได้
นักพัฒนาหลายคนคิดว่าอินเทอร์เฟซและคลาสนามธรรมมีความคล้ายคลึงกัน แต่ในความเป็นจริงแล้ว สิ่งนี้ไม่เป็นความจริงเลย ลองดูความแตกต่างที่สำคัญระหว่างพวกเขา

อินเทอร์เฟซคืออะไร

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

เมื่อใดควรใช้อินเทอร์เฟซ

อินเทอร์เฟซมีประโยชน์มากสำหรับการแยกโค้ดและการนำความหลากหลายไปใช้ เราเห็นสิ่งนี้ได้ใน JDK ด้วยList interface :
public interface List<E> extends Collection<E> {

    int size();
    boolean isEmpty();
    boolean add(E e);
    E remove(int index);
    void clear();
}
ดังที่คุณคงสังเกตเห็นแล้วว่าโค้ดนี้แม้จะสั้นแต่ก็มีคำอธิบายค่อนข้างมาก เราสามารถเห็นลายเซ็นวิธีการที่จะใช้ในการใช้วิธีการในส่วนต่อประสานโดยใช้คลาสที่เป็นรูปธรรมได้อย่างง่ายดาย อินเทอร์เฟซรายการประกอบด้วยสัญญาที่ArrayList , Vector , LinkedListและคลาสอื่นๆ สามารถนำมาใช้ได้ หากต้องการใช้ความหลากหลาย เราสามารถประกาศประเภทของตัวแปรของเราโดยใช้Listจากนั้นเลือกอินสแตนซ์ที่มีอยู่ นี่เป็นอีกตัวอย่างหนึ่ง:
List list = new ArrayList();
System.out.println(list.getClass());

 List list = new LinkedList();
 System.out.println(list.getClass());
ผลลัพธ์คือ:
คลาส java.util.ArrayList คลาส java.util.LinkedList
ในกรณีนี้ วิธีการนำไปใช้สำหรับArrayList , LinkedListและVectorจะแตกต่างกัน ซึ่งเป็นสถานการณ์ที่ดีเยี่ยมสำหรับการใช้อินเทอร์เฟซ หากคุณสังเกตเห็นว่ามีคลาสจำนวนมากอยู่ในคลาสพาเรนต์ซึ่งมีการดำเนินการของเมธอดเดียวกัน แต่มีพฤติกรรมต่างกัน ในสถานการณ์เช่นนี้ ขอแนะนำให้ใช้อินเทอร์เฟซ ต่อไปเรามาดูตัวเลือกต่างๆ ในการใช้อินเทอร์เฟซกัน

การเอาชนะวิธีการอินเทอร์เฟซ

ดังที่เราทราบกันดีอยู่แล้วว่าอินเทอร์เฟซเป็นสัญญาประเภทหนึ่งที่ต้องดำเนินการโดยคลาสที่เป็นรูปธรรม วิธีการอินเทอร์เฟซ นั้นเป็น นามธรรมโดยปริยายและต้องมีการใช้งานคลาสอย่างเป็นรูปธรรม นี่คือตัวอย่าง:
public class OverridingDemo {
  public static void main(String[] args) {
    Challenger challenger = new JavaChallenger();
    challenger.doChallenge();
  }
}

interface Challenger {
  void doChallenge();
}

class JavaChallenger implements Challenger {
  @Override
  public void doChallenge() {
    System.out.println("Challenge done!");
  }
}
บทสรุป:
ท้าทายเสร็จแล้ว!
โปรดทราบว่าวิธีการอินเทอร์เฟซนั้นเป็นนามธรรมโดยปริยาย ซึ่งหมายความว่าเราไม่จำเป็นต้องประกาศให้เป็นนามธรรมอย่างชัดเจน

ตัวแปรคงที่

กฎอีกข้อที่ต้องจำคืออินเทอร์เฟซสามารถมีได้เฉพาะตัวแปรคงที่เท่านั้น นี่คือตัวอย่าง:
public class Challenger {

  int number = 7;
  String name = "Java Challenger";

}
ที่นี่ทั้งสองตัวแปรเป็นค่าสุดท้ายและคงที่โดยปริยาย ซึ่งหมายความว่าสิ่งเหล่านั้นคงที่ เป็นอิสระจากอินสแตนซ์ และไม่สามารถเปลี่ยนแปลงได้ ตอนนี้เราจะพยายามเปลี่ยนตัวแปรใน อินเทอร์เฟซ Challengerสมมติว่าดังนี้:
Challenger.number = 8;
Challenger.name = "Another Challenger";
ซึ่งจะทำให้เกิดข้อผิดพลาดในการรวบรวม:
ไม่สามารถกำหนดค่าให้กับตัวแปรสุดท้าย 'หมายเลข' ไม่สามารถกำหนดค่าให้กับตัวแปรสุดท้าย 'ชื่อ'

วิธีการเริ่มต้น

เมื่อมีการแนะนำวิธีการเริ่มต้นใน Java 8 นักพัฒนาบางคนคิดว่าพวกเขาจะเหมือนกับคลาสนามธรรม อย่างไรก็ตาม สิ่งนี้ไม่เป็นความจริงเนื่องจากอินเทอร์เฟซไม่สามารถมีสถานะได้ วิธีการเริ่มต้นอาจมีการใช้งาน แต่วิธีนามธรรมไม่มี วิธีการเริ่มต้นเป็นผลมาจากนวัตกรรมที่มีนิพจน์แลมบ์ดาและสตรีม แต่เราต้องใช้อย่างระมัดระวัง วิธีการใน JDK ที่ใช้วิธีการเริ่มต้นคือforEach ()ซึ่งเป็นส่วนหนึ่งของ อินเทอร์เฟซ Iterable แทนที่จะคัดลอกโค้ดลงในแต่ละIterableเราสามารถใช้forEach method ซ้ำได้ :
default void forEach(Consumer<? super T> action) {
  // Code implementation here...
การใช้งาน Iterable ใดๆสามารถใช้ เมธอด forEach()ได้โดยไม่ต้องมีการใช้งานเมธอดใหม่ จากนั้นเราสามารถใช้รหัสซ้ำด้วยวิธีเริ่มต้นได้ มาสร้างวิธีการเริ่มต้นของเราเองกัน:
public class DefaultMethodExample {

  public static void main(String[] args) {
    Challenger challenger = new JavaChallenger();
    challenger.doChallenge();
  }

}

class JavaChallenger implements Challenger { }

interface Challenger {

  default void doChallenge() {
    System.out.println("Challenger doing a challenge!");
  }
}
ผลลัพธ์:
ผู้ท้าชิงทำสิ่งที่ท้าทาย!
สำหรับวิธีการเริ่มต้น สิ่งสำคัญคือต้องทราบว่าแต่ละวิธีดังกล่าวจำเป็นต้องได้รับการปฏิบัติ วิธีการเริ่มต้นไม่สามารถเป็นแบบคงที่ได้ ตอนนี้เรามาดูคลาสนามธรรมกันดีกว่า

แก่นแท้ของคลาสนามธรรม

คลาสนามธรรมสามารถมีสถานะพร้อมตัวแปรอินสแตนซ์ได้ ซึ่งหมายความว่าสามารถใช้และแก้ไขตัวแปรอินสแตนซ์ได้ นี่คือตัวอย่าง:
public abstract class AbstractClassMutation {

  private String name = "challenger";

  public static void main(String[] args) {
    AbstractClassMutation abstractClassMutation = new AbstractClassImpl();
    abstractClassMutation.name = "mutated challenger";
    System.out.println(abstractClassMutation.name);
  }

}

class AbstractClassImpl extends AbstractClassMutation { }
บทสรุป:
ผู้ท้าชิงกลายพันธุ์

วิธีนามธรรมในคลาสนามธรรม

เช่นเดียวกับอินเทอร์เฟซ คลาสนามธรรมสามารถมีเมธอดนามธรรมได้ วิธีนามธรรมคือวิธีการที่ไม่มีเนื้อหา ต่างจากอินเทอร์เฟซ วิธีการเชิงนามธรรมในคลาสนามธรรมจะต้องได้รับการประกาศอย่างชัดเจนว่าเป็นนามธรรม นี่คือตัวอย่าง:
public abstract class AbstractMethods {

  abstract void doSomething();

}
และนี่คือความพยายามที่จะประกาศวิธีการโดยไม่ต้องมีการนำไปปฏิบัติและไม่มี คีย์เวิร์ดabstract :
public abstract class AbstractMethods {
   void doSomethingElse();
}
ขออภัย ส่งผลให้เกิดข้อผิดพลาดในการรวบรวม:
ไม่มีเนื้อความของวิธีการหรือประกาศบทคัดย่อ

เมื่อใดควรใช้คลาสนามธรรม

แนะนำให้ใช้คลาสนามธรรมเมื่อคุณต้องการใช้สถานะที่ไม่แน่นอน ตัวอย่างเช่น Java Collections Framework มี คลาส AbstractListที่ใช้สถานะของตัวแปร ในกรณีที่คุณไม่จำเป็นต้องรักษาสถานะคลาส โดยปกติควรใช้อินเทอร์เฟซจะดีกว่า

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

จากมุมมองของการเขียนโปรแกรมเชิงวัตถุ ข้อแตกต่างที่สำคัญระหว่างอินเทอร์เฟซและคลาสนามธรรมก็คือ อินเทอร์เฟซไม่สามารถมีสถานะได้ ในขณะที่คลาสนามธรรมสามารถมีสถานะพร้อมกับตัวแปรอินสแตนซ์ได้ ข้อแตกต่างที่สำคัญอีกประการหนึ่งคือคลาสสามารถใช้อินเทอร์เฟซได้มากกว่าหนึ่งอินเทอร์เฟซ แต่สามารถขยายคลาสนามธรรมได้เพียงคลาสเดียวเท่านั้น โซลูชันนี้ขึ้นอยู่กับข้อเท็จจริงที่ว่าการสืบทอดหลายรายการ (ขยายมากกว่าหนึ่งคลาส) สามารถนำไปสู่การหยุดชะงักของโค้ดได้ นักพัฒนาภาษา Java ตัดสินใจหลีกเลี่ยงสิ่งนี้ ข้อแตกต่างอีกประการหนึ่งคืออินเทอร์เฟซสามารถใช้งานได้โดยคลาสหรือขยายโดยอินเทอร์เฟซ แต่คลาสสามารถขยายได้เท่านั้น สิ่งสำคัญคือต้องทราบว่านิพจน์แลมบ์ดาสามารถใช้ได้กับอินเทอร์เฟซการทำงานเท่านั้น (หมายถึงอินเทอร์เฟซที่มีเพียงวิธีเดียวเท่านั้น) ในขณะที่คลาสนามธรรมที่มีวิธีนามธรรมเพียงวิธีเดียวไม่สามารถใช้นิพจน์แลมบ์ดาได้ ต่อไปนี้เป็นข้อแตกต่างเพิ่มเติมระหว่างคลาสนามธรรมและอินเทอร์เฟซ อินเตอร์เฟซ:
  • สามารถมีได้เฉพาะตัวแปรคงที่สุดท้ายเท่านั้น อินเทอร์เฟซไม่สามารถเปลี่ยนสถานะของตนเองได้
  • คลาสสามารถใช้หลายอินเทอร์เฟซได้
  • สามารถนำไปใช้งานได้โดยใช้คีย์เวิร์ด Implements อินเทอร์เฟซสามารถขยายอินเทอร์เฟซอื่นได้
  • วิธีการสามารถใช้ได้เฉพาะฟิลด์สุดท้ายแบบคงที่ พารามิเตอร์ หรือตัวแปรท้องถิ่นเท่านั้น
  • เฉพาะอินเทอร์เฟซที่ใช้งานได้เท่านั้นที่สามารถใช้ฟังก์ชัน lambda ใน Java ได้
  • ไม่สามารถมีตัวสร้างได้
  • อาจมีวิธีการเชิงนามธรรม
  • สามารถมีวิธีการเริ่มต้นและแบบคงที่ (แนะนำใน Java 8)
  • สามารถมีวิธีส่วนตัวพร้อมการใช้งาน (แนะนำใน Java 9)
คลาสนามธรรม:
  • สามารถมีอินสแตนซ์หรือตัวแปรคงที่ใดๆ ก็ได้ เปลี่ยนแปลงหรือไม่เปลี่ยนรูปได้
  • คลาสสามารถขยายคลาสนามธรรมได้เพียงคลาสเดียวเท่านั้น
  • อาจมีอินสแตนซ์ของฟิลด์ พารามิเตอร์ หรือตัวแปรท้องถิ่นที่ไม่แน่นอน
  • คลาสนามธรรมที่มีวิธีนามธรรมเพียงวิธีเดียวไม่สามารถใช้นิพจน์แลมบ์ดาได้
  • อาจมีตัวสร้าง
  • มีวิธีไหนก็ได้
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION