JavaRush /จาวาบล็อก /Random-TH /คลาสนามธรรมใน Java พร้อมตัวอย่างที่เป็นรูปธรรม

คลาสนามธรรมใน Java พร้อมตัวอย่างที่เป็นรูปธรรม

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

เหตุใดคลาสจึงเรียกว่า "นามธรรม"

คุณคงจำได้ว่า "นามธรรม" คืออะไร - เราได้กล่าวถึงไปแล้ว :) หากคุณลืมกะทันหันก็ไม่เป็นไรจำไว้ว่านี่คือหลักการของ OOPตามที่เมื่อออกแบบคลาสและสร้างวัตถุจำเป็นต้องเน้น เฉพาะคุณสมบัติหลักของเอนทิตีและละทิ้งคุณสมบัติรอง ตัวอย่างเช่น หากเรากำลังออกแบบชั้นเรียนSchoolTeacher- ครูในโรงเรียน - เราไม่จำเป็นต้องมีคุณลักษณะ " ความสูง " แท้จริงแล้ว คุณลักษณะนี้ไม่สำคัญสำหรับครู แต่ถ้าเราสร้างคลาสในโปรแกรมBasketballPlayer- นักบาสเก็ตบอล - ความสูงจะกลายเป็นหนึ่งในคุณสมบัติหลัก ดังนั้นคลาสนามธรรมจึงเป็น "ช่องว่าง" ที่เป็นนามธรรมและใกล้เคียงที่สุดสำหรับกลุ่มของคลาสในอนาคต ไม่สามารถใช้การเตรียมการนี้ในรูปแบบที่เสร็จสมบูรณ์ได้ - มัน "ดิบ" เกินไป แต่มันอธิบายสถานะทั่วไปและพฤติกรรมบางอย่างที่คลาสในอนาคต - ผู้สืบทอดของคลาสนามธรรม - จะมี

ตัวอย่างคลาสนามธรรม Java

ลองดูตัวอย่างง่ายๆ เกี่ยวกับรถยนต์:
public abstract class Car {

   private String model;
   private String color;
   private int maxSpeed;

   public abstract void gas();

   public abstract void brake();

   public String getModel() {
       return model;
   }

   public void setModel(String model) {
       this.model = model;
   }

   public String getColor() {
       return color;
   }

   public void setColor(String color) {
       this.color = color;
   }

   public int getMaxSpeed() {
       return maxSpeed;
   }

   public void setMaxSpeed(int maxSpeed) {
       this.maxSpeed = maxSpeed;
   }
}
นี่คือลักษณะของคลาสนามธรรมที่ง่ายที่สุด อย่างที่คุณเห็น ไม่มีอะไรพิเศษ :) เราต้องการมันเพื่ออะไร? ก่อนอื่น เขาอธิบายถึงสิ่งที่เราต้องการในลักษณะที่เป็นนามธรรมที่สุดเท่าที่จะเป็นไปได้ นั่นคือรถยนต์ คำว่านามธรรมอยู่ที่นี่ด้วยเหตุผล ไม่มี "เครื่องจักรเพียงอย่างเดียว" ในโลก มีทั้งรถบรรทุก รถแข่ง รถเก๋ง คูเป้ เอสยูวี คลาสนามธรรมของเราเป็นเพียง "พิมพ์เขียว" ซึ่งเราจะสร้างคลาสรถยนต์ในภายหลัง
public class Sedan extends Car {

   @Override
   public void gas() {
       System.out.println("The sedan accelerates!");
   }

   @Override
   public void brake() {
       System.out.println("The sedan slows down!");
   }

}
นี่เหมือนกับที่เราพูดถึงในการบรรยายเรื่องมรดกมาก มีเพียงที่นั่นเท่านั้นที่เรามีคลาสCarและวิธีการของมันที่ไม่ใช่นามธรรม แต่โซลูชันนี้มีข้อเสียหลายประการ ซึ่งได้รับการแก้ไขในคลาสนามธรรม ก่อนอื่นไม่สามารถสร้างอินสแตนซ์ของคลาสนามธรรมได้:
public class Main {

   public static void main(String[] args) {

       Car car = new Car(); // Error! The Car class is abstract!
   }
}
“เคล็ดลับ” นี้ถูกนำมาใช้โดยผู้สร้าง Java โดยเฉพาะ โปรดจำไว้ว่า: คลาสนามธรรมเป็นเพียงพิมพ์เขียวสำหรับคลาส "ปกติ" ในอนาคต คุณไม่จำเป็นต้องมีสำเนาภาพวาดใช่ไหม? ดังนั้นจึงไม่จำเป็นต้องสร้างอินสแตนซ์ของคลาสนามธรรม :) และหากคลาสนั้นCarไม่ใช่นามธรรม เราก็สามารถสร้างอ็อบเจ็กต์ของมันได้อย่างง่ายดาย:
public class Car {

   private String model;
   private String color;
   private int maxSpeed;

   public void gas() {
       // some logic
   }

   public  void brake() {
       // some logic
   }
}


public class Main {

   public static void main(String[] args) {

       Car car = new Car(); // Everything is OK, the machine has been created
   }
}
ตอนนี้เรามีรถแปลกๆ อยู่ในโปรแกรม ไม่ใช่รถบรรทุก ไม่ใช่รถแข่ง ไม่ใช่รถเก๋ง แต่เป็นรถทั่วไป “เป็นเพียงเครื่องจักร” ที่ไม่มีอยู่ในธรรมชาติเท่านั้น ตัวอย่างเดียวกันนี้สามารถให้กับสัตว์ได้ ลองนึกภาพว่าถ้าวัตถุปรากฏในโปรแกรมของคุณAnimal- " แค่สัตว์ " มันเป็นประเภทไหน, เป็นของครอบครัวอะไร, มีลักษณะอย่างไร - ยังไม่ชัดเจน คงจะแปลกถ้าเห็นเขาอยู่ในรายการ ไม่มี "สัตว์" ในธรรมชาติ เฉพาะสุนัข แมว สุนัขจิ้งจอก ตุ่น และอื่นๆ คลาสนามธรรมทำให้เราเป็นอิสระจาก " เพียงวัตถุ " พวกมันให้สถานะและพฤติกรรมพื้นฐานแก่เรา ตัวอย่างเช่น รถยนต์ทุกคันต้องมีรุ่นสีและความเร็วสูงสุดและต้องสามารถเติมน้ำมันและเบรกได้ด้วย นั่นคือทั้งหมดที่ นี่เป็นโครงร่างนามธรรมทั่วไปจากนั้นคุณจึงออกแบบคลาสที่คุณต้องการเอง โปรดทราบ:สองวิธีในคลาสนามธรรมยังถูกกำหนดให้เป็นabstractและไม่ได้นำไปใช้เลย เหตุผลก็เหมือนกัน: คลาสนามธรรมไม่ได้สร้าง "พฤติกรรมเริ่มต้น" สำหรับ "เครื่องจักรเพียงอย่างเดียว" พวกเขาแค่บอกว่าควรจะสร้างรถยนต์ได้ทั้งหมด อย่างไรก็ตาม หากคุณยังคงต้องการพฤติกรรมเริ่มต้น คุณสามารถใช้วิธีการในคลาสนามธรรมได้ Java ไม่ได้ห้ามสิ่งนี้:
public abstract class Car {

   private String model;
   private String color;
   private int maxSpeed;

   public void gas() {
       System.out.println("Let's go!");
   }

   public abstract void brake();

   //getters and setters
}


public class Sedan extends Car {

   @Override
   public void brake() {
       System.out.println("The sedan slows down!");
   }

}

public class Main {

   public static void main(String[] args) {

       Sedan sedan = new Sedan();
       sedan.gas();
   }
}
เอาต์พุตคอนโซล: “เร่งความเร็ว!” อย่างที่คุณเห็น เราได้ใช้วิธีหนึ่งในคลาสนามธรรม แต่ไม่ได้ใช้วิธีที่สอง เป็นผลให้พฤติกรรมของคลาสของเราSedanถูกแบ่งออกเป็นสองส่วน: ถ้าคุณเรียกใช้เมธอดนั้นgas()มันจะ "ดึงขึ้น" จากคลาสนามธรรมหลักCarและbrake()เราได้กำหนดวิธีการในคลาสSedanใหม่ ปรากฎว่าสะดวกและยืดหยุ่นมาก แต่ตอนนี้ชั้นเรียนของเราไม่มีนามธรรมมากนัก ? ท้ายที่สุดแล้ว วิธีการของเขาครึ่งหนึ่งได้ถูกนำมาใช้แล้ว ในความเป็นจริง - และนี่คือคุณลักษณะที่สำคัญมาก - คลาสจะเป็นนามธรรมหากวิธีการอย่างน้อยหนึ่งวิธีเป็น abstract อย่างน้อยหนึ่งในสอง อย่างน้อยหนึ่งในพันวิธี - มันไม่สำคัญ เรายังสามารถนำวิธีการทั้งหมดไปใช้และไม่ทิ้งวิธีที่เป็นนามธรรมไว้เลย จะมีคลาสนามธรรมที่ไม่มีวิธีนามธรรม โดยหลักการแล้วสิ่งนี้เป็นไปได้และคอมไพเลอร์จะไม่สร้างข้อผิดพลาด แต่เป็นการดีกว่าที่จะไม่ทำเช่นนี้: คำว่านามธรรมจะสูญเสียความหมายและเพื่อนโปรแกรมเมอร์ของคุณจะประหลาดใจมากเมื่อเห็นสิ่งนี้ :/ ยิ่งไปกว่านั้นหากวิธีการ ถูกทำเครื่องหมายด้วยคำว่านามธรรม แต่ละคลาสลูกหลานจะต้องนำไปใช้หรือประกาศให้เป็นนามธรรม มิฉะนั้นคอมไพเลอร์จะเกิดข้อผิดพลาด แน่นอนว่า แต่ละคลาสสามารถสืบทอดจากคลาสนามธรรมเพียงคลาสเดียว ดังนั้นในแง่ของการสืบทอด จึงไม่มีความแตกต่างระหว่างคลาสนามธรรมและคลาสปกติ ไม่สำคัญว่าเราจะสืบทอดมาจากคลาสนามธรรมหรือจากคลาสปกติ สามารถมีคลาสพาเรนต์ได้เพียงคลาสเดียวเท่านั้น

เหตุใดจึงไม่มีการสืบทอดหลายคลาสใน Java

เราได้กล่าวไปแล้วว่า Java ไม่มีการสืบทอดหลายรายการ แต่เราไม่เข้าใจว่าทำไมจริงๆ มาลองกันตอนนี้เลย ประเด็นก็คือหาก Java มีการสืบทอดหลายรายการ คลาสย่อยจะไม่สามารถตัดสินใจได้ว่าควรเลือกพฤติกรรมใด สมมติว่าเรามีสองคลาส - TosterและNuclearBomb:
public class Toster {


 public void on() {

       System.out.println("The toaster is on, the toast is getting ready!");
   }

   public void off() {

       System.out.println("The toaster is off!");
   }
}


public class NuclearBomb {

   public void on() {

       System.out.println("Взрыв!");
   }
}
อย่างที่คุณเห็น ทั้งสองมีวิธีon()การ ในกรณีของเครื่องปิ้งขนมปัง เครื่องจะเริ่มปิ้งขนมปัง และในกรณีของระเบิดนิวเคลียร์ จะทำให้เกิดการระเบิด โอ้ :/ ทีนี้ลองจินตนาการว่าคุณตัดสินใจ (จู่ๆ ฉันก็ไม่รู้ว่าทำไม!) เพื่อสร้างบางสิ่งที่อยู่ระหว่างนั้น และนี่คือชั้นเรียนของคุณ - MysteriousDevice! แน่นอนว่าโค้ดนี้ใช้งานไม่ได้ และเรานำเสนอเป็นเพียงตัวอย่างของ "มันจะเป็นไปได้อย่างไร":
public class MysteriousDevice extends Toster, NuclearBomb {

   public static void main(String[] args) {

       MysteriousDevice mysteriousDevice = new MysteriousDevice();
       mysteriousDevice.on(); // And what should happen here? Will we get a toast, or a nuclear apocalypse?
   }
}
มาดูกันว่าเราได้อะไรบ้าง อุปกรณ์ลึกลับนี้มาจากทั้งเครื่องปิ้งขนมปังและระเบิดนิวเคลียร์ ทั้งสองมีเมธอดon()และด้วยเหตุนี้ จึงไม่ชัดเจนว่าon()ควรใช้เมธอดใดกับวัตถุMysteriousDeviceหากเราเรียกมัน วัตถุจะไม่สามารถเข้าใจสิ่งนี้ได้ เช่นเดียวกับเชอร์รี่บนเค้ก: ระเบิดนิวเคลียร์ไม่มีวิธีการoff()ดังนั้นหากเราเดาผิดก็จะไม่มีทางปิดอุปกรณ์ได้ คลาสนามธรรมใน Java พร้อมตัวอย่างที่เป็นรูปธรรม - 2 เป็นเพราะความสับสนนี้อย่างชัดเจน เมื่อวัตถุไม่ชัดเจนว่าควรเลือกพฤติกรรมใด ผู้สร้าง Java จึงละทิ้งมรดกหลายอย่าง อย่างไรก็ตาม คุณจำได้ว่าคลาส Java ใช้อินเทอร์เฟซจำนวนมาก อย่างไรก็ตาม คุณได้พบคลาสนามธรรมอย่างน้อยหนึ่งคลาสในการศึกษาของคุณแล้ว! แม้ว่าบางทีฉันอาจจะไม่ได้สังเกตเห็นมัน :)
public abstract class Calendar implements Serializable, Cloneable, Comparable<Calendar>
Calendarนี่คือ เพื่อน เก่าของคุณ - ชั้นเรียน ถือเป็นนามธรรมและมีทายาทหลายราย หนึ่งในนั้นGregorianCalendarคือ คุณเคยใช้มันในบทเรียนเกี่ยวกับวันที่แล้ว :) ดูเหมือนทุกอย่างจะชัดเจน เหลือเพียงจุดเดียว: อะไรคือความแตกต่างพื้นฐานระหว่างคลาสนามธรรมและอินเทอร์เฟซ ? เหตุใดพวกเขาจึงเพิ่มทั้งสองอย่างลงใน Java และไม่ จำกัด ตัวเองเพียงอันเดียว? เท่านี้ก็น่าจะเพียงพอแล้ว เราจะพูดถึงเรื่องนี้ในการบรรยายครั้งต่อไป! พบกันใหม่:)
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION