คำถามและคำตอบสัมภาษณ์ OOP มากกว่า 50 ข้อ (2026)

เตรียมตัวสำหรับการสัมภาษณ์แบบ OOPs หรือยัง? ถึงเวลาคิดคำถามที่คุณอาจถูกถามและวิธีตอบ การจะผ่านขั้นตอนนี้ให้สำเร็จได้นั้นต้องอาศัยความเข้าใจทั้งพื้นฐานและเชิงลึกของการสัมภาษณ์แบบ OOPs

โอกาสในสายงานนี้กำลังขยายตัวอย่างรวดเร็ว โดยความเชี่ยวชาญทางเทคนิคและประสบการณ์วิชาชีพกลายเป็นรากฐานสำคัญของความสำเร็จ ไม่ว่าคุณจะเป็นมือใหม่ที่มุ่งมั่นไขข้อข้องใจเบื้องต้น นักพัฒนาระดับกลางที่กำลังฝึกฝนทักษะการวิเคราะห์ หรือผู้เชี่ยวชาญอาวุโสที่มีประสบการณ์ระดับพื้นฐาน 5 ปีหรือ 10 ปี คำถามและคำตอบเหล่านี้ล้วนให้ข้อมูลเชิงลึกที่นำไปใช้ได้จริง ผู้จัดการฝ่ายบุคคล หัวหน้าทีม และผู้บริหารระดับสูงต่างคาดหวังให้ผู้สมัครแสดงทักษะที่เหนือกว่าทฤษฎีสู่การประยุกต์ใช้ขั้นสูงที่สอดคล้องกับเทรนด์ของอุตสาหกรรม

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

คำถามและคำตอบสัมภาษณ์ OOPS

1) การเขียนโปรแกรมเชิงวัตถุ (OOP) คืออะไร และเหตุใดจึงสำคัญ?

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

👉 ดาวน์โหลด PDF ฟรี: คำถามและคำตอบสัมภาษณ์ OOPS


2) อธิบายหลักการสำคัญของ OOP พร้อมตัวอย่าง

หลักการพื้นฐานสี่ประการของ OOP มีดังนี้:

  1. encapsulation – ซ่อนการใช้งานภายในแต่เปิดเผยฟังก์ชันที่จำเป็น ตัวอย่าง: คลาสบัญชีธนาคารที่มีตัวแปรยอดคงเหลือส่วนตัว
  2. สิ่งที่เป็นนามธรรม – แสดงเฉพาะรายละเอียดที่สำคัญและซ่อนความซับซ้อน ตัวอย่าง: การใช้รีโมททีวีโดยไม่เข้าใจวงจรไฟฟ้า
  3. มรดก – การนำแอตทริบิวต์และพฤติกรรมจากคลาสแม่มาใช้ซ้ำ ตัวอย่าง: คลาส Dog ที่สืบทอดมาจาก Animal
  4. ความหลากหลาย – ความสามารถในการใช้รูปแบบต่างๆ ได้หลายรูปแบบ เช่น การโอเวอร์โหลดเมธอดและการโอเวอร์ไรด์ ตัวอย่าง: ฟังก์ชัน draw() ที่มีพฤติกรรมแตกต่างกันสำหรับวงกลม สี่เหลี่ยม หรือสามเหลี่ยม
หลัก จุดมุ่งหมาย ตัวอย่าง
encapsulation จำกัด การเข้าถึง ยอดคงเหลือส่วนตัวในระบบธนาคาร
สิ่งที่เป็นนามธรรม ซ่อนความซับซ้อน อินเทอร์เฟซรีโมททีวี
มรดก ใช้ซ้ำและขยาย ยานพาหนะ → รถยนต์, รถบรรทุก
ความหลากหลาย พฤติกรรมหลายอย่าง draw() วิธี

3) คลาสแตกต่างจากอ็อบเจ็กต์อย่างไร?

A ชั้น คือแบบแปลนหรือแม่แบบที่กำหนดโครงสร้างและพฤติกรรมของวัตถุ ในขณะที่ วัตถุ คืออินสแตนซ์ของคลาส คลาสจะระบุแอตทริบิวต์และเมธอด แต่จะไม่ครอบครองหน่วยความจำจนกว่าจะสร้างอ็อบเจ็กต์ อ็อบเจ็กต์เป็นตัวแทนของเอนทิตีในโลกแห่งความเป็นจริงและเก็บค่าจริง ตัวอย่างเช่น Car คลาสกำหนดคุณสมบัติเช่น color และ engineTypeแต่วัตถุ myCar = Car("Red", "V6") ถือค่าเฉพาะเจาะจง วงจรชีวิตของวัตถุโดยทั่วไปประกอบด้วยการสร้าง การใช้งาน และการทำลาย


4) การสืบทอดใน OOP มีกี่ประเภท?

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

  1. มรดกเดียว – ซับคลาสได้รับการสืบทอดมาจากซูเปอร์คลาสหนึ่ง
  2. มรดกหลายรายการ – ซับคลาสสืบทอดมาจากซูเปอร์คลาสหลายตัว (รองรับใน C++ แต่ไม่ใช่โดยตรง Java).
  3. มรดกหลายระดับ – ซับคลาสจะสืบทอดมาจากซับคลาสอื่น ทำให้เกิดลำดับชั้นขึ้นมา
  4. มรดกตามลำดับชั้น – คลาสหลายคลาสสืบทอดมาจากคลาสฐานเดียว
  5. มรดกแบบผสมผสาน – การผสมผสานการสืบทอดประเภทต่างๆ
ประเภท ตัวอย่าง
เดียว นักเรียน → บุคคล
แพลตฟอร์มที่หลากหลาย พนักงานสืบทอดจากบุคคล + คนงาน (C++)
หลายระดับ ปู่ย่าตายาย → พ่อแม่ → ลูก
ตามลำดับชั้น สุนัข แมว ม้า สืบทอดจากสัตว์
เป็นลูกผสม การผสมผสานกันของสองประเภทขึ้นไป

5) คุณสามารถอธิบายความแตกต่างระหว่างการโอเวอร์โหลดเมธอดและการโอเวอร์ไรด์เมธอดได้หรือไม่

วิธีการโอเวอร์โหลด เกิดขึ้นเมื่อมีวิธีการสองวิธีหรือมากกว่าในคลาสเดียวกันที่มีชื่อเดียวกัน แต่มีพารามิเตอร์ (จำนวนหรือประเภท) แตกต่างกัน แสดงถึงความหลากหลายในเวลาคอมไพล์

วิธีการเอาชนะ เกิดขึ้นเมื่อซับคลาสมีการใช้งานเฉพาะของเมธอดที่กำหนดไว้แล้วในคลาสแม่ ซึ่งแสดงถึงพหุสัณฐานแบบรันไทม์

ลักษณะ โอเวอร์โหลด ที่เอาชนะ
ผูกพัน รวบรวมเวลา Runtime
พารามิเตอร์ ต้องแตกต่างกัน จะต้องเหมือนกัน
ประเภทผลตอบแทน สามารถแตกต่างกันได้ จะต้องเหมือนกัน
ใช้กรณี ความยืดหยุ่น ความเชี่ยวชาญ

ตัวอย่าง:

  • โอเวอร์โหลด: add(int, int) และ add(double, double) ในชั้นเรียนหนึ่ง
  • การเอาชนะ: Animal.speak() แทนที่โดย Dog.speak().

6) การห่อหุ้มมีประโยชน์ต่อการพัฒนาซอฟต์แวร์อย่างไร

การห่อหุ้มช่วยปรับปรุงความเป็นโมดูล ลดความซับซ้อน และเพิ่มความปลอดภัยของข้อมูลด้วยการจำกัดการเข้าถึงสถานะภายในโดยตรง ช่วยให้นักพัฒนาสามารถเปลี่ยนแปลงรายละเอียดการใช้งานได้โดยไม่ส่งผลกระทบต่อโค้ดภายนอก ตัวอย่างเช่น ใน BankAccount คลาส, balance แอตทริบิวต์เป็นแบบส่วนตัว และการเข้าถึงจะถูกควบคุมผ่านวิธีการสาธารณะ deposit() และ withdraw()วิธีนี้ช่วยให้มั่นใจได้ว่าธุรกรรมถูกต้องและป้องกันการจัดการโดยไม่ได้รับอนุญาต ข้อดีหลัก ๆ มีดังนี้:

  • การป้องกันจากการรบกวนที่ไม่ได้ตั้งใจ
  • ความสามารถในการใช้ตรรกะการตรวจสอบ
  • เพิ่มความสามารถในการบำรุงรักษาผ่านการเชื่อมต่อแบบหลวม

7) อธิบายการแยกส่วนโดยใช้การเปรียบเทียบกับโลกแห่งความเป็นจริง

การแยกส่วนช่วยลดความซับซ้อนของระบบที่ซับซ้อนโดยเปิดเผยเฉพาะคุณสมบัติที่จำเป็นในขณะที่ซ่อนรายละเอียด ตัวอย่างในโลกแห่งความเป็นจริงคือ เครื่องชงกาแฟ: ผู้ใช้กดปุ่มเพื่อชงกาแฟโดยไม่เข้าใจกลไกพื้นฐาน เช่น การต้มน้ำ การบด หรือการกรอง ในการเขียนโปรแกรม การสร้างนามธรรมทำได้ผ่านคลาสหรืออินเทอร์เฟซแบบนามธรรม ตัวอย่างเช่น ใน Java, คลาสที่เป็นนามธรรม Shape อาจกำหนดวิธีการแบบนามธรรม draw()ในขณะที่คลาสย่อยเช่น Circle or Rectangle มอบการนำไปใช้งานที่เป็นรูปธรรม ส่งเสริมความยืดหยุ่นและการนำโค้ดกลับมาใช้ใหม่ ขณะเดียวกันก็ลดความซับซ้อนลง


8) constructor และ destructor คืออะไร? ต่างกันอย่างไร?

A นวกรรมิก เป็นเมธอดพิเศษที่เรียกใช้งานโดยอัตโนมัติเมื่อสร้างอ็อบเจ็กต์ จุดประสงค์คือเพื่อเริ่มต้นสถานะของอ็อบเจ็กต์ ในภาษาส่วนใหญ่ ชื่อของเมธอดจะตรงกับชื่อคลาส ผู้ทำลาย จะถูกเรียกเมื่อวัตถุถูกทำลาย โดยปกติจะเพื่อปลดปล่อยทรัพยากร

ความแตกต่างที่สำคัญ:

  • นวกรรมิก เริ่มต้นวัตถุ; destructor ทำความสะอาดทรัพยากร
  • Constructor สามารถโอเวอร์โหลดได้ แต่ destructor ทำไม่ได้
  • ตัวสร้างจะถูกเรียกใช้งานเมื่อสร้าง และตัวทำลายจะถูกเรียกใช้งานเมื่อสิ้นสุด

ตัวอย่างใน C++:

class Student {
public:
    Student() { cout << "Constructor called"; } 
    ~Student() { cout << "Destructor called"; } 
}; 

9) ความแตกต่างระหว่างคลาสแบบนามธรรมและอินเทอร์เฟซคืออะไร?

An คลาสนามธรรม สามารถประกอบด้วยทั้งวิธีการเชิงนามธรรม (ไม่ได้นำไปใช้งาน) และวิธีการที่เป็นรูปธรรม (นำไปใช้งาน) ในขณะที่ อินเตอร์เฟซ มีเฉพาะวิธีการแบบนามธรรม (ในภาษาส่วนใหญ่ แม้ว่าจะเป็นสมัยใหม่ Java อนุญาตให้ใช้วิธีเริ่มต้น) คลาสที่เป็นนามธรรมรองรับการสืบทอดแบบเดี่ยว ในขณะที่อินเทอร์เฟซอนุญาตให้มีการสืบทอดหลายแบบ

แง่มุม คลาสนามธรรม อินเตอร์เฟซ
วิธีการ นามธรรม + รูปธรรม บทคัดย่อ (สามารถใช้วิธีการเริ่มต้นได้)
ตัวแปร สามารถมีตัวแปรอินสแตนซ์ได้ ค่าคงที่เท่านั้น
มรดก เดียว แพลตฟอร์มที่หลากหลาย
ใช้กรณี ฐานร่วมกันกับการนำไปปฏิบัติบางอย่าง สัญญาจ้างเรียน

ตัวอย่าง:

  • คลาสนามธรรม Animal พร้อมนำไปปฏิบัติ eat() และบทคัดย่อ makeSound().
  • อินเตอร์เฟซ Flyable สีสดสวย fly() ที่เรียนเหมือน Bird or Airplane จะต้องปฏิบัติตาม

10) Polymorphism แสดงออกมาใน OOP อย่างไร?

พหุสัณฐาน (Polymorphism) อนุญาตให้เอนทิตีหนึ่งๆ มีรูปแบบได้หลายแบบ มีสองประเภทหลักๆ ได้แก่

  • โพลีมอร์ฟิซึมในเวลาคอมไพล์ (แบบคงที่) – ทำได้โดยการโอเวอร์โหลดวิธีการหรือการโอเวอร์โหลดตัวดำเนินการ ตัวอย่าง: หลายเวอร์ชันของ calculate() วิธีการที่มีพารามิเตอร์ที่แตกต่างกัน
  • โพลีมอร์ฟิซึมแบบรันไทม์ (ไดนามิก) – ทำได้โดยการแทนที่วิธีการ ตัวอย่าง: A Shape การเรียกตัวแปรอ้างอิง draw() วิธีการทำงานแตกต่างกันขึ้นอยู่กับว่ามันชี้ไปที่ Circle or Square วัตถุ.

ซึ่งช่วยให้มีความยืดหยุ่น ขยายได้ และบำรุงรักษาง่ายยิ่งขึ้นในแอปพลิเคชันขนาดใหญ่


11) ตัวปรับแต่งการเข้าถึงที่แตกต่างกันใน OOP มีอะไรบ้าง และมีความสำคัญอย่างไร

ตัวปรับแต่งการเข้าถึง (Access Modifier) ​​จะกำหนดความสามารถในการมองเห็นและการเข้าถึงคลาส เมธอด และตัวแปร โดยจะควบคุมวิธีการเปิดเผยข้อมูลและพฤติกรรมต่อส่วนอื่นๆ ของโปรแกรม เพื่อให้มั่นใจถึงการห่อหุ้มและความปลอดภัย

ประเภททั่วไป:

  • สาธารณะ – สามารถเข้าถึงได้จากทุกที่ในโปรแกรม
  • Private – เข้าถึงได้เฉพาะภายในคลาสที่กำหนดเท่านั้น
  • มีการป้องกัน – สามารถเข้าถึงได้ภายในคลาสและคลาสย่อยของมัน
  • ค่าเริ่มต้น/ภายใน (เฉพาะภาษา) – สามารถเข้าถึงได้ภายในแพ็คเกจหรือชุดประกอบเดียวกัน
เปลี่ยนแปลง การเข้าถึง ตัวอย่าง
สาธารณะ เปิดให้ทุกคน สาธารณะ getName() วิธี
Private เฉพาะคลาสเดียวกันเท่านั้น Private balance ตัวแปร
มีการป้องกัน คลาส + คลาสย่อย มีการป้องกัน calculateSalary()
ภายใน (C#) การประกอบแบบเดียวกัน ภายใน Logger ชั้น

ตัวปรับเปลี่ยนการเข้าถึงช่วยให้แน่ใจว่าข้อมูลถูกซ่อน มีการแบ่งส่วน และเปิดเผยรหัสที่ได้รับการควบคุม


12) การผูกแบบคงที่แตกต่างจากการผูกแบบไดนามิกใน OOP อย่างไร

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

การผูกแบบไดนามิก (การผูกข้อมูลล่าช้า) เกิดขึ้นขณะรันไทม์ ซึ่งการเรียกใช้เมธอดจะขึ้นอยู่กับชนิดข้อมูลจริงของอ็อบเจ็กต์ วิธีนี้ทำให้เกิดความหลากหลายและความยืดหยุ่น แต่อาจต้องแลกมาด้วยต้นทุนด้านประสิทธิภาพ

แง่มุม การผูกมัดแบบคงที่ การผูกแบบไดนามิก
ความละเอียด เวลาในการรวบรวม Runtime
ตัวอย่าง โอเวอร์โหลด ที่เอาชนะ
ความยืดหยุ่น ต่ำ จุดสูง
ความเร็ว ได้เร็วขึ้น ช้าลงเล็กน้อย

ตัวอย่างเช่นใน Java, เรียกการแทนที่ toString() วิธีการนี้ขึ้นอยู่กับชนิดของวัตถุจริง ทำให้เป็นกรณีของการผูกแบบไดนามิก


13) วงจรชีวิตของอ็อบเจ็กต์ใน OOP คืออะไร

วงจรชีวิตของวัตถุ หมายถึงขั้นตอนต่าง ๆ ที่วัตถุต้องผ่านตั้งแต่การสร้างไปจนถึงการทำลาย การเข้าใจวงจรชีวิตนี้จะช่วยให้นักพัฒนาสามารถจัดการหน่วยความจำและทรัพยากรได้อย่างมีประสิทธิภาพ

ขั้นตอน:

  1. การสร้าง – วัตถุได้รับการสร้างตัวอย่างโดยใช้ตัวสร้าง
  2. การเขียนอักษรย่อ – คุณลักษณะจะได้รับการกำหนดค่า โดยมักจะผ่านพารามิเตอร์ของตัวสร้าง
  3. การใช้ – เรียกใช้วิธีการและจัดการข้อมูล
  4. การสิ้นสุด/การทำลาย – วัตถุนั้นอยู่นอกขอบเขตหรือถูกทำลายอย่างชัดเจน ใน C++, ตัวทำลายล้างจัดการการทำความสะอาด; ใน Java หรือ C# การรวบรวมขยะจะจัดการหน่วยความจำ

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


14) อธิบายแนวคิดเกี่ยวกับฟังก์ชันเพื่อนและคลาสเพื่อน

In C++, ฟังก์ชันของเพื่อน และ ชั้นเรียนเพื่อน อนุญาตให้ฟังก์ชันหรือคลาสภายนอกเข้าถึงสมาชิกแบบส่วนตัวและแบบป้องกันของคลาสอื่นได้ ข้อยกเว้นเหล่านี้ถือเป็นหลักการห่อหุ้ม (encapsulation) ซึ่งใช้ในสถานการณ์ที่ต้องการความร่วมมืออย่างใกล้ชิด

  • ฟังก์ชั่นเพื่อน: ประกาศโดยใช้ friend คำสำคัญภายในคลาส ตัวอย่าง: ฟังก์ชันที่โอเวอร์โหลด << ตัวดำเนินการเพื่อแสดงเนื้อหาของคลาส
  • ห้องเรียนเพื่อน: ให้สิทธิ์การเข้าถึงโดยตรงแก่คลาสอื่นแก่สมาชิกส่วนตัว ตัวอย่าง: A Logger ชั้นเรียนเป็นเพื่อนของ BankAccount เพื่อบันทึกรายการธุรกรรม

แม้ว่าการใช้เพื่อนมากเกินไปจะทรงพลัง แต่ก็อาจทำให้การห่อหุ้มอ่อนแอลงได้ ดังนั้นต้องใช้ด้วยความประหยัดและจงใจ


15) ฟังก์ชันเสมือนและฟังก์ชันเสมือนบริสุทธิ์คืออะไร

A ฟังก์ชันเสมือน เป็นฟังก์ชันสมาชิกในคลาสฐานที่ประกาศด้วย virtual คำสำคัญ ช่วยให้คลาสที่สืบทอดมาสามารถแทนที่พฤติกรรมของมันได้ รองรับโพลีมอร์ฟิซึมแบบรันไทม์ ตัวอย่าง: Shape::draw() แทนที่ใน Circle และ Square.

A ฟังก์ชันเสมือนบริสุทธิ์ เป็นฟังก์ชันเสมือนที่ไม่มีการใช้งาน กำหนดเป็น = 0มันทำให้คลาสเป็นนามธรรมเพื่อให้แน่ใจว่าคลาสที่สืบทอดมาจะต้องใช้งานฟังก์ชัน

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

ในบริบทการสัมภาษณ์ ฟังก์ชันเสมือนบริสุทธิ์มีความสำคัญต่อการบังคับใช้การแยกส่วนและการออกแบบสถาปัตยกรรมที่ขยายได้


16) ข้อดีและข้อเสียของ OOP มีอะไรบ้าง?

OOP นำมาซึ่งประโยชน์มากมายแต่ก็มีข้อจำกัดอยู่บ้างเช่นกัน

ข้อดี:

  • ความสามารถในเรอุส โดยการถ่ายทอดทางพันธุกรรม
  • modularity โดยการจัดระเบียบโค้ดเป็นคลาส
  • ความยืดหยุ่น ที่มีรูปร่างหลากหลาย
  • ⁠ความปลอดภัย ผ่านการห่อหุ้มและซ่อนข้อมูล

ข้อเสีย:

  • ความซับซ้อน:OOP อาจทำให้เกิดการเรียนรู้ที่ซับซ้อน
  • ค่าใช้จ่ายด้านประสิทธิภาพการสร้างวัตถุและการรวบรวมขยะสามารถทำให้การดำเนินการช้าลง
  • การใช้หน่วยความจำ:วัตถุมักจะใช้หน่วยความจำมากกว่าโค้ดเชิงกระบวนการ
ข้อดี ข้อเสีย
ใช้รหัสซ้ำ ความซับซ้อนที่เพิ่มขึ้น
การบำรุงรักษาที่ดีขึ้น การดำเนินการช้าลงในบางกรณี
การรักษาความปลอดภัยด้วยการห่อหุ้ม ขนาดโปรแกรมที่ใหญ่ขึ้น
scalability ไม่เหมาะกับงานเล็กๆ น้อยๆ เสมอไป

ดังนั้น OOP จึงมีประสิทธิภาพสูงสำหรับแอปพลิเคชันขนาดใหญ่ แต่อาจไม่เหมาะกับสคริปต์ขนาดเล็ก


17) ข้อยกเว้นได้รับการจัดการอย่างไรใน OOP?

การจัดการข้อยกเว้นเป็นกลไกในการจัดการข้อผิดพลาดรันไทม์อย่างราบรื่นโดยไม่ทำให้โปรแกรมหยุดทำงาน ใน OOP ข้อยกเว้นคืออ็อบเจ็กต์ที่แสดงถึงสถานะข้อผิดพลาด

กระบวนการทั่วไปประกอบด้วย:

  1. ลองบล็อก – โค้ดที่อาจเกิดข้อยกเว้นได้
  2. จับบล็อก – จัดการประเภทข้อยกเว้นที่เฉพาะเจาะจง
  3. ในที่สุดก็บล็อค (ใน Java/C#) – ดำเนินการล้างโค้ดโดยไม่คำนึงถึงข้อยกเว้น

ตัวอย่างใน Java:

try {
    int result = 10 / 0;
} catch (ArithmeticException e) {
    System.out.println("Division by zero not allowed.");
} finally {
    System.out.println("Execution completed.");
}

ประโยชน์ ได้แก่ การจัดการข้อผิดพลาดที่สะอาดขึ้น การป้องกันความล้มเหลวฉับพลัน และการแยกตรรกะการจัดการข้อผิดพลาดจากตรรกะทางธุรกิจ


18) วัตถุจะใช้หน่วยความจำเสมอหรือไม่ และมีการจัดสรรหน่วยความจำอย่างไร

ใช่ วัตถุใช้หน่วยความจำ แต่การจัดสรรขึ้นอยู่กับการใช้งานภาษา ใน OOP:

  • การจัดสรรแบบคงที่:หน่วยความจำสำหรับตัวแปรระดับคลาส (คงที่) จะถูกจัดสรรหนึ่งครั้งในเวลาคอมไพล์
  • การจัดสรรฮีป:โดยปกติแล้วอินสแตนซ์ (อ็อบเจ็กต์) จะถูกเก็บไว้ในหน่วยความจำฮีป ซึ่งได้รับการจัดสรรแบบไดนามิกในระหว่างการรันไทม์
  • การจัดสรรสแต็ก:การอ้างอิงหรือตัวชี้ไปยังวัตถุอาจอยู่ในสแต็ก

ตัวอย่างใน Java:

Car myCar = new Car("Red");

ที่นี่อ้างอิง myCar อยู่บนสแต็ก ขณะที่อ็อบเจ็กต์จริงอยู่บนฮีป การจัดการหน่วยความจำอย่างมีประสิทธิภาพต้องอาศัยความเข้าใจในคอนสตรัคเตอร์ ดีสตรัคเตอร์ และการรวบรวมขยะ


19) ความแตกต่างระหว่างองค์ประกอบและการสืบทอดคืออะไร?

ทั้งสองอย่างนี้เป็นกลไกสำหรับการนำโค้ดกลับมาใช้ใหม่ แต่มีความแตกต่างกันโดยพื้นฐาน

  • มรดก:ความสัมพันธ์แบบ “is-a” ที่คลาสย่อยได้รับพฤติกรรมมาจากคลาสหลัก ตัวอย่าง: Car สืบทอดมาจาก Vehicle.
  • ส่วนประกอบ: ความสัมพันธ์แบบ “has-a” ที่คลาสประกอบด้วยอ็อบเจ็กต์หนึ่งรายการหรือมากกว่าจากคลาสอื่น ตัวอย่าง: Car มี Engine.
แง่มุม มรดก ส่วนประกอบ
ความสัมพันธ์ อิซา-อะ มี-เอ
การแต่งงานกัน แน่น หลวม
ความยืดหยุ่น Less มีความยืดหยุ่น ยืดหยุ่นมากขึ้น
ใช้กรณี โครงสร้างลำดับชั้น องค์ประกอบพฤติกรรมแบบไดนามิก

แนวทางปฏิบัติที่ดีที่สุดในยุคใหม่มักจะสนับสนุน การเรียบเรียงเหนือการสืบทอด เพื่อความยืดหยุ่นที่มากขึ้นและการเชื่อมโยงที่ลดลง


20) รูปแบบการออกแบบเกี่ยวข้องกับ OOP อย่างไร

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

ตัวอย่างเช่น:

  • รูปแบบการสร้างสรรค์ (เช่น Singleton, Factory) – ลดความซับซ้อนในการสร้างวัตถุ
  • รูปแบบโครงสร้าง (เช่น อะแดปเตอร์ ตัวตกแต่ง) – กำหนดความสัมพันธ์ระหว่างคลาส
  • รูปแบบพฤติกรรม (เช่น ผู้สังเกตการณ์ กลยุทธ์) – จัดการการสื่อสารวัตถุ

ยกตัวอย่างเช่น รูปแบบผู้สังเกตการณ์ ช่วยให้สามารถอัปเดตวัตถุหลายรายการ (ผู้สังเกตการณ์) เมื่อวัตถุเปลี่ยนสถานะ ซึ่งมักใช้ในระบบที่ขับเคลื่อนด้วยเหตุการณ์ การรวมรูปแบบการออกแบบเข้าด้วยกันแสดงให้เห็นถึงความเชี่ยวชาญที่ลึกซึ้งยิ่งขึ้นใน OOP นอกเหนือจากพื้นฐาน


21) Constructor ใน OOP มีกี่ประเภท?

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

  1. ตัวสร้างเริ่มต้น – ไม่รับพารามิเตอร์ใดๆ เริ่มต้นด้วยค่าเริ่มต้น
  2. ตัวสร้างพารามิเตอร์ – ยอมรับพารามิเตอร์เพื่อกำหนดค่าเมื่อสร้าง
  3. คัดลอกตัวสร้าง – สร้างวัตถุใหม่เป็นสำเนาของวัตถุที่มีอยู่
class Student {
public:
    string name;
    Student() { name = "Unknown"; }                 // Default
    Student(string n) { name = n; }                 // Parameterized
    Student(const Student &s) { name = s.name; }    // Copy
};
ประเภท จุดมุ่งหมาย ตัวอย่าง
ค่าเริ่มต้น ไม่มีข้อโต้แย้ง Student()
พารามิเตอร์ เริ่มต้นด้วยค่า Student("John")
คัดลอก โคลนที่มีอยู่ Student(s1)

ความยืดหยุ่นนี้ช่วยให้นักพัฒนาสามารถจัดการการสร้างวัตถุได้หลายวิธี


22) Destructor แตกต่างจากวิธี finalize อย่างไร

A ผู้ทำลาย เป็นคุณลักษณะ OOP (เช่น ใน C++ และ C#) ใช้เพื่อปลดปล่อยทรัพยากรเมื่อวัตถุถูกทำลาย โดยจะถูกเรียกใช้งานโดยอัตโนมัติเมื่อวัตถุอยู่นอกขอบเขต

การขอ วิธีการ finalize() in Java เป็นแนวคิดที่คล้ายกันแต่ถูกยกเลิกไปแล้วตั้งแต่ Java 9 เนื่องจากตัวรวบรวมขยะจัดการหน่วยความจำอย่างมีประสิทธิภาพอยู่แล้ว และการพึ่งพาการสรุปข้อมูลทำให้เกิดความไม่แน่นอน

แง่มุม destructor วิธีการสรุปขั้นสุดท้าย
ภาษาที่ใช้ C++, ค# Java (เลิกใช้แล้ว)
การภาวนา เมื่อวัตถุถูกทำลาย ก่อนที่ GC จะลบวัตถุออก
Control กำหนดขึ้น ไม่กำหนด
ใช้กรณี ทรัพยากรฟรี การล้างข้อมูลแบบเดิม

แนวปฏิบัติสมัยใหม่สนับสนุนการจัดการทรัพยากรที่ชัดเจนโดยใช้ ลองกับทรัพยากร in Java or การใช้บล็อก ใน C#


23) บทบาทของคืออะไร this ตัวชี้หรือการอ้างอิง?

การขอ this คำสำคัญหมายถึงอินสแตนซ์ของวัตถุปัจจุบัน บทบาทของคำนี้แตกต่างกันไปตามภาษา แต่โดยทั่วไปประกอบด้วย:

  • การแยกความแตกต่างระหว่างตัวแปรอินสแตนซ์และพารามิเตอร์วิธีการ
  • การส่งวัตถุปัจจุบันเป็นอาร์กิวเมนต์ไปยังวิธีการอื่น
  • การส่งคืนวัตถุปัจจุบันจากวิธีการ (การเชื่อมโยงวิธีการ)

ตัวอย่างใน Java:

class Employee {
    String name;
    Employee(String name) {
        this.name = name; // disambiguates parameter vs variable
    }
}

In C++, this เป็นตัวชี้จริงในขณะที่ Java และ C# มันคือข้อมูลอ้างอิง มันช่วยเพิ่มความชัดเจนและทำให้รูปแบบการเขียนโปรแกรมมีความลื่นไหล


24) ความแตกต่างระหว่างคลาสและโครงสร้างคืออะไร?

ทั้งคลาสและโครงสร้างเป็นประเภทที่ผู้ใช้กำหนด แต่แตกต่างกันในจุดประสงค์และการใช้งาน

แง่มุม ชั้น โครงสร้าง
การเข้าถึงเริ่มต้น Private สาธารณะ
รองรับการสืบทอด ใช่ ไม่ (C++ จำกัดเพียงเท่านั้น)
หน่วยความจำ กอง (โดยทั่วไป) สแต็ค (โดยทั่วไป)
ใช้กรณี หน่วยงานที่ซับซ้อน คอนเทนเนอร์ข้อมูลน้ำหนักเบา

ตัวอย่าง:

  • ชั้น: Car คลาสที่มีวิธีการและสถานะ
  • โครงสร้าง: Point โครงสร้างที่แสดงถึง (x, y) พิกัด.

ใน OOP ยุคใหม่ คลาสจะโดดเด่นด้วยคุณสมบัติขั้นสูง เช่น การสืบทอดและรูปแบบที่หลากหลาย ในขณะที่โครงสร้างจะสงวนไว้สำหรับวัตถุข้อมูลน้ำหนักเบาที่ไม่สามารถเปลี่ยนแปลงได้


25) สมาชิกแบบคงที่แตกต่างจากสมาชิกแบบอินสแตนซ์อย่างไร

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

สมาชิกอินสแตนซ์ เป็นของแต่ละอ็อบเจ็กต์ โดยมีค่าเฉพาะต่ออินสแตนซ์

ตัวอย่างใน Java:

class Counter {
    static int count = 0; // shared
    int id;
    Counter() { id = ++count; }
}

ที่นี่ count ติดตามจำนวนวัตถุที่ถูกสร้างในขณะที่ id แตกต่างกันไปในแต่ละวัตถุ

ลักษณะ สมาชิกแบบคงที่ สมาชิกอินสแตนซ์
ขอบเขต ระดับชั้นเรียน ระดับวัตถุ
หน่วยความจำ สำเนาเดียว หลายสำเนา
ทางเข้า ชื่อคลาส การอ้างอิงวัตถุ

สมาชิกแบบคงที่เหมาะอย่างยิ่งสำหรับค่าคงที่ ยูทิลิตี้ หรือตัวนับที่ใช้ร่วมกัน


26) คลาสที่ปิดผนึกหรือตัวปรับเปลี่ยนคืออะไร?

A ชั้นเรียนปิดผนึก จำกัดการสืบทอดเพื่อไม่ให้คลาสอื่นสืบทอดจากคลาสนั้นได้ แนวคิดนี้ใช้เพื่อบังคับใช้การไม่เปลี่ยนแปลงและความปลอดภัย

  • In C#ที่ sealed คีย์เวิร์ดป้องกันการสืบทอดเพิ่มเติม
  • In Java (จาก JDK 15)คลาสที่ปิดผนึกจะอนุญาตเฉพาะคลาสย่อยบางคลาสเท่านั้น ซึ่งช่วยปรับปรุงการควบคุมลำดับชั้นของคลาส

ตัวอย่าง (Java 17):

sealed class Shape permits Circle, Square {}
final class Circle extends Shape {}
final class Square extends Shape {}

ประโยชน์ที่ได้รับ:

  • ป้องกันการใช้งานคลาสฐานในทางที่ผิด
  • ปรับปรุงความสามารถในการบำรุงรักษาโดยการจำกัดส่วนขยาย
  • มีประโยชน์สำหรับการสร้างลำดับชั้นประเภทที่ครอบคลุมในนิพจน์สวิตช์

27) คุณสามารถอธิบายความแตกต่างระหว่าง polymorphism ในเวลาคอมไพล์และในเวลารันไทม์พร้อมตัวอย่างได้หรือไม่?

ความหลากหลายของเวลาคอมไพล์ (การผูกล่วงหน้า) จะแก้ไขการเรียกใช้เมธอดในเวลาคอมไพล์ โดยทั่วไปจะทำได้โดยใช้การโอเวอร์โหลดเมธอด

ความหลากหลายของรันไทม์ (การผูกมัดล่าช้า) จะแก้ไขการเรียกในระหว่างการดำเนินการ ซึ่งโดยทั่วไปจะทำได้โดยการแทนที่วิธีการ

ตัวอย่างใน Java:

// Compile-time
class MathOps {
    int add(int a, int b) { return a + b; }
    double add(double a, double b) { return a + b; }
}

// Runtime
class Animal { void speak() { System.out.println("Generic"); } }
class Dog extends Animal { void speak() { System.out.println("Bark"); } }
แง่มุม รวบรวมเวลา Runtime
ผูกพัน ก่อน ปลาย
ลักษณะ โอเวอร์โหลด ที่เอาชนะ
ประสิทธิภาพ ได้เร็วขึ้น เรามีความยืดหยุ่น
ตัวอย่าง add(int, int) Dog.speak()

28) หลักการออกแบบเช่น SOLID ใน OOP คืออะไร?

การขอ หลักการที่มั่นคง เป็นแนวทางในการสร้างการออกแบบ OOP ที่สามารถบำรุงรักษาและปรับขนาดได้:

  1. Sหลักการความรับผิดชอบแบบ ingle – ชั้นเรียนควรมีเหตุผลหนึ่งประการในการเปลี่ยนแปลง
  2. Oหลักการปากกา/ปิด – เปิดเพื่อขยาย ปิดเพื่อปรับเปลี่ยน
  3. Lหลักการแทนที่ของ iskov – ประเภทย่อยจะต้องสามารถแทนที่ประเภทฐานได้
  4. Iหลักการแยกอินเทอร์เฟซ – เลือกใช้อินเทอร์เฟซที่เล็กและเฉพาะเจาะจง
  5. Dหลักการผกผันของการพึ่งพา – ขึ้นอยู่กับสิ่งที่เป็นนามธรรม ไม่ใช่สิ่งที่เป็นรูปธรรม

ตัวอย่าง: แทนที่จะเป็นแบบโมโนลิธิก Report การจัดการคลาส การสร้าง การส่งออก และการแสดงผล แบ่งคลาสออกเป็นคลาสย่อยๆ เพื่อปรับปรุงความเป็นโมดูลและความสามารถในการทดสอบ SOLID สอดคล้องกับแนวปฏิบัติที่ดีที่สุดและรองรับรูปแบบการออกแบบมากมาย


29) ความแตกต่างระหว่างการคัดลอกแบบตื้นและการคัดลอกแบบลึกคืออะไร?

  • สำเนาตื้น:คัดลอกเฉพาะการอ้างอิงเท่านั้น ไม่ใช่ตัววัตถุเอง การเปลี่ยนแปลงในสิ่งหนึ่งจะส่งผลต่ออีกสิ่งหนึ่ง
  • สำเนาลึก:ทำซ้ำทุกสิ่งเพื่อสร้างวัตถุที่เป็นอิสระ

ตัวอย่างใน Java:

// Shallow copy
List list1 = new ArrayList<>();
list1.add("A");
List list2 = list1; // both refer to same object

// Deep copy
List list3 = new ArrayList<>(list1); // new object
ลักษณะ สำเนาตื้น สำเนาลึก
ระดับการคัดลอก อ้างอิงเท่านั้น กราฟวัตถุเต็ม
ความเป็นอิสระ ไม่ ใช่
ประสิทธิภาพ ได้เร็วขึ้น ช้าลง
ใช้กรณี วัตถุที่ไม่เปลี่ยนแปลง โครงสร้างที่เปลี่ยนแปลงได้และซับซ้อน

การเข้าใจความแตกต่างนี้ถือเป็นสิ่งสำคัญในการป้องกันผลข้างเคียงที่ไม่พึงประสงค์


30) ตัวอย่างในชีวิตจริงแสดงให้เห็นแนวคิด OOP ได้อย่างไร

การเปรียบเทียบในโลกแห่งความเป็นจริงทำให้ OOP ชัดเจนขึ้น:

  • encapsulation:ยาเม็ดแคปซูลซ่อนส่วนผสมหลายอย่างไว้ เช่นเดียวกับคลาสที่ซ่อนข้อมูล
  • สิ่งที่เป็นนามธรรม:รีโมททีวีซ่อนสายไฟภายในที่ซับซ้อนจนเห็นเพียงปุ่มต่างๆ
  • มรดก:สุนัขได้รับลักษณะต่างๆ มาจากสัตว์ (เช่น การหายใจ การเคลื่อนไหว)
  • ความหลากหลาย: ฟังก์ชัน makeSound() มีพฤติกรรมแตกต่างกันระหว่างแมว (เหมียว) กับสุนัข (เห่า)

การเปรียบเทียบดังกล่าวแสดงให้เห็นว่า OOP สร้างแบบจำลองระบบในโลกแห่งความเป็นจริงอย่างเป็นธรรมชาติได้อย่างไร ตัวอย่างเช่น ใบสมัครธนาคาร สรุปรายละเอียดบัญชี ใช้การสืบทอดสำหรับประเภทบัญชี ใช้พหุสัณฐานในการทำธุรกรรม และสรุปการดำเนินการจากผู้ใช้ การเชื่อมโยงเหล่านี้ช่วยให้ผู้สมัครสามารถอธิบายแนวคิดได้อย่างชัดเจนในการสัมภาษณ์


31) ความแตกต่างระหว่างการโอเวอร์โหลดและการโอเวอร์ไรด์ด้วยตัวอย่างคืออะไร

การโอเวอร์โหลดและการโอเวอร์ไรด์เป็นกลไกที่แตกต่างกันสองประการใน OOP ที่เปิดใช้งานความหลากหลาย

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

ตัวอย่างใน Java:

// Overloading
class Calculator {
    int add(int a, int b) { return a + b; }
    double add(double a, double b) { return a + b; }
}

// Overriding
class Animal { void speak() { System.out.println("Generic"); } }
class Dog extends Animal { void speak() { System.out.println("Bark"); } }
ลักษณะ โอเวอร์โหลด ที่เอาชนะ
ผูกพัน รวบรวมเวลา Runtime
พารามิเตอร์ ต้องแตกต่างกัน จะต้องเหมือนกัน
ประเภทการคืนสินค้า สามารถแตกต่างกันได้ จะต้องเหมือนกัน
ใช้กรณี ความยืดหยุ่น ความเชี่ยวชาญ

32) มีการใช้คลาสแบบนามธรรมในการออกแบบ OOP อย่างไร

คลาสแบบนามธรรม (Abstract class) มอบโครงร่างบางส่วนสำหรับคลาสอื่นๆ คลาสเหล่านี้ไม่สามารถสร้างอินสแตนซ์ได้โดยตรง แต่สามารถประกอบด้วยทั้งเมธอดแบบนามธรรม (โดยไม่ต้องนำไปปฏิบัติ) และเมธอดแบบรูปธรรม (พร้อมนำไปปฏิบัติ) ซึ่งช่วยให้นักพัฒนาสามารถบังคับใช้โครงสร้างร่วมกันได้ ในขณะที่ยังคงความยืดหยุ่นให้กับซับคลาส

ตัวอย่าง:

abstract class Shape {
    abstract void draw();
    void info() { System.out.println("I am a shape"); }
}
class Circle extends Shape {
    void draw() { System.out.println("Drawing Circle"); }
}	

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


33) อินเทอร์เฟซคืออะไร และแตกต่างจากคลาสแบบนามธรรมอย่างไร

An อินเตอร์เฟซ กำหนดสัญญาที่คลาสต้องปฏิบัติตามโดยการนำเมธอดทั้งหมดไปใช้งาน โดยเน้นที่ "สิ่งที่" คลาสควรทำ ไม่ใช่ "วิธีการ" ซึ่งแตกต่างจากคลาสเชิงนามธรรม โดยทั่วไปอินเทอร์เฟซจะไม่มีสถานะและกำหนดพฤติกรรมเพียงอย่างเดียว

ตัวอย่างใน Java:

interface Flyable {
    void fly();
}
class Bird implements Flyable {
    public void fly() { System.out.println("Bird flies"); }
}
แง่มุม คลาสนามธรรม อินเตอร์เฟซ
วิธีการ นามธรรม + รูปธรรม บทคัดย่อ (ด้วยวิธีการเริ่มต้นในสมัยใหม่ Java)
ตัวแปร สามารถมีฟิลด์ได้ ค่าคงที่เท่านั้น
มรดก เดียว แพลตฟอร์มที่หลากหลาย
จุดมุ่งหมาย ฐานทั่วไป สัญญาพฤติกรรม

อินเทอร์เฟซรองรับการสืบทอดหลายแบบ ทำให้เหมาะสำหรับการกำหนดความสามารถ เช่น Serializable or Comparable.


34) ตัวระบุการเข้าถึงคืออะไร C++/Javaและแตกต่างกันอย่างไรในแต่ละภาษา?

ตัวระบุการเข้าถึงจะกำหนดความสามารถในการมองเห็นของสมาชิกคลาส

  • C++: ส่วนตัว (ค่าเริ่มต้นสำหรับคลาส), ได้รับการปกป้อง, สาธารณะ
  • Java:ส่วนตัว, ได้รับการปกป้อง, สาธารณะ และเริ่มต้น (แพ็คเกจส่วนตัว)
ตัวระบุ C++ Java
Private ภายในชั้นเรียนเท่านั้น ภายในชั้นเรียนเท่านั้น
มีการป้องกัน คลาส + คลาสย่อย คลาส + คลาสย่อย + แพ็คเกจเดียวกัน
สาธารณะ ทุกแห่ง ทุกแห่ง
ค่าเริ่มต้น ไม่สามารถใช้งาน ภายในแพ็คเกจเท่านั้น

ตัวอย่างเช่นใน C++, struct ค่าเริ่มต้นเป็น สาธารณะในขณะที่ class ค่าเริ่มต้นเป็น ส่วนตัวในขณะที่ใน Java, ค่าเริ่มต้น/แพ็คเกจส่วนตัว อนุญาติให้เข้าถึงได้เฉพาะภายในแพ็คเกจเดียวกันเท่านั้น


35) การโอเวอร์โหลดตัวดำเนินการคืออะไร และมีข้อจำกัดอะไรบ้าง?

Operaการโอเวอร์โหลด Tor ช่วยให้นักพัฒนาสามารถกำหนดตัวดำเนินการใหม่สำหรับประเภทที่ผู้ใช้กำหนดขึ้นเอง ซึ่งช่วยปรับปรุงการอ่านโค้ด รองรับหลักๆ ใน C++.

ตัวอย่าง:

class Complex {
public:
    int real, imag;
    Complex operator+(const Complex &c) {
        return {real + c.real, imag + c.imag};
    }
};

แม้ว่าจะทรงพลัง แต่ก็มีข้อจำกัด:

  • ไม่ใช่ว่าตัวดำเนินการทั้งหมดจะสามารถโอเวอร์โหลดได้ (เช่น ::, .?).
  • การใช้มากเกินไปอาจทำให้ความชัดเจนลดลง
  • เพิ่มความซับซ้อนในการเรียนรู้สำหรับทีมที่ไม่คุ้นเคยกับตัวดำเนินการแบบกำหนดเอง

ดังนั้น ควรใช้การโอเวอร์โหลดตัวดำเนินการอย่างรอบคอบ โดยเฉพาะสำหรับคลาสทางคณิตศาสตร์หรือเฉพาะโดเมนที่ความหมายของตัวดำเนินการตามธรรมชาติช่วยปรับปรุงการอ่านได้


36) วิธีการแบบคงที่แตกต่างจากวิธีการแบบอินสแตนซ์อย่างไร

เมธอดแบบสแตติกเป็นของคลาส ไม่ใช่อินสแตนซ์ และสามารถเรียกใช้งานโดยใช้ชื่อคลาสได้ เมธอดแบบอินสแตนซ์ทำงานบนอ็อบเจ็กต์เฉพาะ

ตัวอย่างใน Java:

class MathUtils {
    static int square(int x) { return x * x; }
    int add(int a, int b) { return a + b; }
}

การใช้งาน:

  • MathUtils.square(4); → วิธีคงที่
  • new MathUtils().add(2, 3); → วิธีการอินสแตนซ์
ลักษณะ วิธีการคงที่ วิธีการอินสแตนซ์
ขอบเขต ระดับชั้นเรียน ระดับวัตถุ
ทางเข้า เฉพาะข้อมูลคงที่ ข้อมูลทั้งแบบคงที่และแบบอินสแตนซ์
การภาวนา ชื่อคลาส การอ้างอิงวัตถุ

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


37) ข้อเสียของ OOP ในโลกแห่งความเป็นจริงคืออะไร

แม้จะมีจุดแข็ง แต่ OOP ก็มีข้อเสียอยู่บ้าง:

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

ตัวอย่าง: ในการพัฒนาเกม เอ็นจิ้นประสิทธิภาพสูงมักต้องการ การออกแบบที่เน้นข้อมูล ผ่าน OOP เพื่อหลีกเลี่ยงภาระงานขณะรันไทม์

ดังนั้น แม้ว่า OOP จะโดดเด่นในเรื่องความสามารถในการบำรุงรักษาและความสามารถในการปรับขนาด แต่ข้อเสียของมันจะต้องชั่งน้ำหนักกับข้อกำหนดของโครงการ


38) การสืบทอดหลายรูปแบบคืออะไร และภาษาต่างๆ จัดการอย่างไร

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

  • C++ รองรับการสืบทอดหลายแบบพร้อมการกำหนดขอบเขตที่ชัดเจน
  • Java และค# หลีกเลี่ยงมันแต่จำลองมันผ่าน อินเตอร์เฟซ.

ตัวอย่างใน C++:

class A { public: void show() {} };
class B { public: void show() {} };
class C : public A, public B {};

ในกรณีนี้การโทร C.show() คลุมเครือเว้นแต่จะมีขอบเขต (C.A::show()).

ดังนั้นภาษาสมัยใหม่จึงนิยมใช้การเขียนหรืออินเทอร์เฟซเพื่อการออกแบบที่ปลอดภัยยิ่งขึ้น


39) การรวบรวมขยะทำงานอย่างไรในภาษา OOP เช่น Java และ C#?

การรวบรวมขยะ (GC) จะเรียกคืนหน่วยความจำโดยอัตโนมัติด้วยการลบวัตถุที่โปรแกรมไม่ได้อ้างอิงอีกต่อไป

ขั้นตอนสำคัญ:

  1. ผลิตโดย – ระบุการอ้างอิงที่ใช้งานอยู่ทั้งหมด
  2. กวาด – ปลดปล่อยหน่วยความจำที่ถูกครอบครองโดยวัตถุที่ไม่มีการอ้างอิง
  3. ขนาดกะทัดรัด (ตัวเลือก) – จัดเรียงหน่วยความจำใหม่เพื่อลดการแตกกระจาย

ตัวอย่างใน Java:

MyObject obj = new MyObject();
obj = null; // eligible for GC

ข้อดี: ป้องกันการรั่วไหลของหน่วยความจำ ลดภาระของนักพัฒนา

ข้อจำกัด: การกำหนดเวลาที่ไม่แน่นอน ประสิทธิภาพการทำงานอาจหยุดชะงัก

C++ ขาด GC ในตัว โดยอาศัยตัวทำลายล้างและตัวชี้อัจฉริยะแทน (std::unique_ptr).


40) ความแตกต่างที่สำคัญระหว่างการเขียนโปรแกรมเชิงกระบวนการและ OOP คืออะไร

การเขียนโปรแกรมเชิงกระบวนการจะจัดระเบียบโค้ดเป็นกระบวนการ (ฟังก์ชัน) ในขณะที่ OOP จะจัดระเบียบให้เป็นอ็อบเจ็กต์

ลักษณะ ขั้นตอน OOP
โฟกัส ฟังก์ชั่นและขั้นตอน วัตถุ (สถานะ + พฤติกรรม)
ข้อมูล ทั่วโลกหรือผ่านระหว่างฟังก์ชั่น ห่อหุ้มอยู่ในวัตถุ
ใช้รหัสซ้ำ ฟังก์ชั่นและลูป การถ่ายทอดทางพันธุกรรม, พหุสัณฐาน
ตัวอย่าง C Java, C++, Python

ตัวอย่าง:

  • ในการเขียนโปรแกรมเชิงกระบวนการ แอปพลิเคชันธนาคารจะมีฟังก์ชันแยกกันสำหรับ deposit() และ withdraw().
  • ใน OOP Account วัตถุจะรวมพฤติกรรมเหล่านี้ไว้ด้วยกัน ซึ่งจะช่วยปรับปรุงการทำงานแบบแยกส่วนและการนำกลับมาใช้ใหม่ได้

การที่ OOP เน้นการสร้างแบบจำลองเอนทิตีในโลกแห่งความเป็นจริงทำให้ OOP เหมาะสมกับระบบขนาดใหญ่ที่ปรับขนาดได้


41) Copy constructor คืออะไร และเหตุใดจึงสำคัญ?

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

ตัวอย่าง:

class Student {
public:
    string name;
    Student(const Student &s) { name = s.name; }
};

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


42) วิธีการคงที่สามารถเข้าถึงสมาชิกที่ไม่คงที่ได้หรือไม่

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

ตัวอย่างใน Java:

class Example {
    int x = 10;
    static void show() {
        // System.out.println(x); // Error
    }
}

อย่างไรก็ตาม วิธีการคงที่สามารถเข้าถึงสมาชิกที่ไม่ใช่แบบคงที่โดยอ้อมได้โดยการสร้างอ็อบเจ็กต์:

Example e = new Example();
System.out.println(e.x);

ข้อจำกัดนี้ช่วยให้มั่นใจถึงความสอดคล้องทางตรรกะ เนื่องจากวิธีการคงที่มีอยู่โดยอิสระจากอ็อบเจ็กต์


43) คลาสฐาน คลาสย่อย และซูเปอร์คลาส คืออะไร?

  • A ชั้นฐาน (หรือซูเปอร์คลาส) ให้คุณลักษณะและพฤติกรรมพื้นฐานสำหรับคลาสอื่น
  • A ประเภทรอง ขยายหรือสืบทอดมาจากคลาสฐาน โดยได้รับคุณลักษณะต่างๆ ในขณะที่เพิ่มหรือแทนที่ฟังก์ชันการทำงาน
  • A ซุปเปอร์คลาส เป็นเพียงชื่ออื่นของคลาสแม่

ตัวอย่าง:

class Vehicle { void move() { System.out.println("Moving"); } }
class Car extends Vehicle { void honk() { System.out.println("Horn"); } }

ที่นี่ Vehicle เป็นฐาน/ซูเปอร์คลาส และ Car เป็นคลาสย่อย ลำดับชั้นนี้ช่วยให้ การนำโค้ดกลับมาใช้ใหม่ และจำลองความสัมพันธ์ในโลกแห่งความเป็นจริง ในการออกแบบ OOP การเลือกการแยกส่วนที่เหมาะสมสำหรับคลาสฐานเป็นสิ่งสำคัญสำหรับความสามารถในการปรับขนาดและการบำรุงรักษา


44) ความแตกต่างระหว่างการผูกแบบคงที่และแบบไดนามิกคืออะไร?

การผูกแบบคงที่ แก้ไขการเรียกใช้เมธอดในเวลาคอมไพล์ (เช่น การโอเวอร์โหลดเมธอด) ในขณะที่ การเชื่อมโยงแบบไดนามิก จะแก้ไขปัญหาเหล่านั้นในระหว่างการรันไทม์ (เช่น การแทนที่วิธีการ)

ตัวอย่าง:

// Static Binding
class MathOps {
    int add(int a, int b) { return a + b; }
}

// Dynamic Binding
class Animal { void speak() { System.out.println("Generic"); } }
class Dog extends Animal { void speak() { System.out.println("Bark"); } }
ลักษณะ การผูกมัดแบบคงที่ การผูกแบบไดนามิก
ความละเอียด เวลาในการรวบรวม Runtime
ตัวอย่าง โอเวอร์โหลด ที่เอาชนะ
ความยืดหยุ่น ต่ำ จุดสูง
ความเร็ว ได้เร็วขึ้น ช้าลงเล็กน้อย

การผูกแบบคงที่ช่วยปรับปรุงประสิทธิภาพ ในขณะที่การผูกแบบไดนามิกรองรับความหลากหลายและความสามารถในการขยาย


45) เหตุใดจึงไม่สามารถสร้างอินสแตนซ์ของคลาสแบบนามธรรมได้

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

ตัวอย่างใน Java:

abstract class Shape {
    abstract void draw();
}
Shape s = new Shape(); // Error

ในทางกลับกัน คลาสแบบนามธรรมจะถูกขยายโดยคลาสย่อยที่เป็นรูปธรรมซึ่งให้การนำไปใช้งาน การออกแบบนี้บังคับใช้ ภาระผูกพันตามสัญญา— ซับคลาสทั้งหมดต้องทำงานตามที่ต้องการให้เสร็จสมบูรณ์ คลาสแบบนามธรรมจึงให้ แม่แบบ สำหรับคลาสที่เกี่ยวข้องในขณะที่ป้องกันอินสแตนซ์บางส่วนที่ไม่สามารถใช้งานได้


46) คลาสนามธรรมสามารถสร้างอินสแตนซ์ได้จำนวนเท่าใด

สามารถสร้างอินสแตนซ์ศูนย์สำหรับคลาสแบบนามธรรมได้ เนื่องจากคลาสแบบนามธรรมอาจมีเมธอดที่ยังไม่ได้ใช้งาน จึงทำให้คลาสไม่สมบูรณ์และไม่สามารถสร้างอินสแตนซ์ได้โดยตรง

อย่างไรก็ตาม นักพัฒนาสามารถ:

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

ตัวอย่าง:

abstract class Animal {
    abstract void makeSound();
}
class Dog extends Animal {
    void makeSound() { System.out.println("Bark"); }
}
Animal a = new Dog(); // Valid

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


47) แนวคิด OOP ใดที่รองรับการนำรหัสกลับมาใช้ซ้ำได้

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

ตัวอย่าง:

class Vehicle { void move() { System.out.println("Moving"); } }
class Car extends Vehicle {}

ที่นี่ Car สืบทอดโดยอัตโนมัติ move() โดยไม่ได้นิยามมันใหม่

ผู้สนับสนุนอื่นๆ ต่อการนำกลับมาใช้ใหม่ได้แก่:

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

48) ตัวระบุการเข้าถึงเริ่มต้นในคำจำกัดความของคลาสคืออะไร?

ตัวระบุการเข้าถึงเริ่มต้นจะแตกต่างกันไปตามภาษา:

  • C++: ในคลาส สมาชิกจะเป็นแบบส่วนตัวตามค่าเริ่มต้น ใน struct สมาชิกจะเป็นแบบสาธารณะตามค่าเริ่มต้น
  • Java:ค่าเริ่มต้น (เรียกอีกอย่างว่าแพ็คเกจส่วนตัว) หมายความว่าสมาชิกสามารถเข้าถึงได้ภายในแพ็คเกจเดียวกันเท่านั้น
  • C#:คลาสจะเป็นแบบภายในตามค่าเริ่มต้น ซึ่งหมายความว่าสามารถเข้าถึงได้ภายในแอสเซมบลีเดียวกัน

ตัวอย่างใน C++:

class Example { int x; }; // x is private by default
struct Example2 { int x; }; // x is public by default

การทำความเข้าใจค่าเริ่มต้นจะช่วยป้องกันการเปิดเผยที่ไม่ได้ตั้งใจหรือการจำกัดสมาชิกคลาส


49) แนวคิด OOP ใดถือเป็นกลไกการนำกลับมาใช้ใหม่

มรดก ได้รับการยอมรับอย่างกว้างขวางว่าเป็นกลไกการนำกลับมาใช้ใหม่ใน OOP ซึ่งช่วยให้ซับคลาสสามารถรับพฤติกรรมและคุณสมบัติของคลาสแม่ได้ จึงช่วยลดความซ้ำซ้อนของโค้ด

ตัวอย่าง:

class Employee { void work() { System.out.println("Working"); } }
class Manager extends Employee {}

Manager สืบทอดโดยอัตโนมัติ work() วิธี

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


50) หลักการ OOP ใดที่รับประกันว่าจะมีการเปิดเผยเฉพาะข้อมูลที่สำคัญเท่านั้น

หลักการก็คือ สิ่งที่เป็นนามธรรม. ซ่อนรายละเอียดการใช้งานและเปิดเผยเฉพาะฟีเจอร์ที่จำเป็นต่อโลกภายนอก

ตัวอย่าง:

เมื่อใช้ a รถผู้ขับขี่จะโต้ตอบกับอุปกรณ์ควบคุมต่างๆ เช่น พวงมาลัยและแป้นเหยียบ แต่ไม่ได้เกี่ยวข้องกับกระบวนการเผาไหม้ภายใน ในทำนองเดียวกัน ในการเขียนโปรแกรม:

abstract class Database {
    abstract void connect();
}

ผู้ใช้ของ Database สนใจแค่เรื่อง connect() ไม่ใช่รายละเอียดที่ซับซ้อนของวิธีการสร้างการเชื่อมต่อ การแยกส่วนส่งเสริมความเรียบง่าย ลดความซับซ้อน และปรับปรุงความสามารถในการบำรุงรักษา


51) หลักการ SOLID ใน OOP คืออะไร และเหตุใดจึงสำคัญ?

การขอ หลักการที่มั่นคง เป็นแนวทางสำคัญห้าประการสำหรับการสร้างระบบเชิงวัตถุที่สามารถบำรุงรักษาได้ ปรับขนาดได้ และยืดหยุ่น:

  1. หลักการความรับผิดชอบเดียว – ชั้นเรียนควรมีเหตุผลเพียงหนึ่งเดียวในการเปลี่ยนแปลง
  2. หลักการเปิด/ปิด – หน่วยงานซอฟต์แวร์ควรเปิดให้มีการขยาย แต่ปิดไม่ให้มีการปรับเปลี่ยน
  3. หลักการทดแทนลิสคอฟ – ควรสามารถแทนที่ประเภทย่อยด้วยประเภทฐานได้โดยไม่เปลี่ยนแปลงความถูกต้อง
  4. หลักการแยกส่วนต่อประสาน – อินเทอร์เฟซเฉพาะเจาะจงขนาดเล็กจำนวนมากจะดีกว่าอินเทอร์เฟซทั่วไปขนาดใหญ่เพียงรายการเดียว
  5. หลักการผกผันการพึ่งพา – ขึ้นอยู่กับสิ่งที่เป็นนามธรรม ไม่ใช่การนำไปปฏิบัติจริง

หลักการเหล่านี้ช่วยลดการเชื่อมโยง ส่งเสริมการทำงานแบบโมดูลาร์ และสอดคล้องกับรูปแบบการออกแบบ ทำให้ระบบง่ายต่อการทดสอบ ขยาย และบำรุงรักษามากขึ้น


52) รูปแบบการออกแบบช่วยเสริม OOP ได้อย่างไร

รูปแบบการออกแบบเป็นโซลูชันที่นำมาใช้ซ้ำได้สำหรับปัญหาที่เกิดขึ้นซ้ำ โดยมักจะใช้ประโยชน์จากหลักการ OOP เช่น การแยกส่วน การห่อหุ้ม การสืบทอด และรูปแบบหลายรูปแบบ

  • รูปแบบการสร้างสรรค์ (เช่น Singleton, Factory) ทำให้การสร้างวัตถุง่ายขึ้น
  • รูปแบบโครงสร้าง (เช่น Adapter, Composite, Decorator) จัดระเบียบโครงสร้างของคลาส
  • รูปแบบพฤติกรรม (เช่น ผู้สังเกตการณ์ กลยุทธ์ การบังคับบัญชา) จัดการการโต้ตอบระหว่างวัตถุ

ยกตัวอย่างเช่น แบบโรงงาน การสร้างวัตถุแบบนามธรรม เพื่อให้แน่ใจว่าไคลเอนต์จะพึ่งพาการสร้างวัตถุแบบนามธรรมมากกว่าคลาสที่เป็นรูปธรรม ซึ่งสอดคล้องกับหลักการ Dependency Inversion Principle ของ SOLID ในการสัมภาษณ์ การอ้างอิงรูปแบบการออกแบบไม่เพียงแต่แสดงให้เห็นถึงความรู้เชิงทฤษฎีเท่านั้น แต่ยังรวมถึงประสบการณ์จริงในการประยุกต์ใช้แนวคิด OOP กับความท้าทายในโลกแห่งความเป็นจริงอีกด้วย


53) ความแตกต่างระหว่างการแต่งเพลงและการสืบทอดคืออะไร และเหตุใดจึงมักนิยมการแต่งเพลงมากกว่า

มรดก แสดงถึงความสัมพันธ์แบบ “เป็น” (เช่น สุนัขเป็นสัตว์) ในขณะที่ ส่วนประกอบ แสดงถึงความสัมพันธ์แบบ “มี-มี” (เช่น รถยนต์มีเครื่องยนต์)

แง่มุม มรดก ส่วนประกอบ
การแต่งงานกัน แน่น หลวม
นำมาใช้ใหม่ ผ่านลำดับชั้น ผ่านความร่วมมือด้านวัตถุ
ความยืดหยุ่น จำกัด (คงที่) สูง (ไดนามิก)
ตัวอย่าง Car extends Vehicle Car has Engine

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


54) ข้อเสียหลักของ OOP ในระบบขนาดใหญ่คืออะไร

แม้ว่า OOP จะได้รับการยอมรับอย่างกว้างขวาง แต่ก็มีข้อจำกัดที่เห็นได้ชัดในระบบขนาดใหญ่หรือระบบที่สำคัญต่อประสิทธิภาพ:

  • โอเวอร์เฮดหน่วยความจำ:วัตถุจะพกพาข้อมูลเมตาซึ่งจะเพิ่มพื้นที่เก็บข้อมูล
  • ปัญหาด้านประสิทธิภาพ:คุณสมบัติเช่นฟังก์ชันเสมือนและการรวบรวมขยะจะเพิ่มต้นทุนรันไทม์
  • ความซับซ้อน:ลำดับชั้นที่ลึกซึ้งอาจสร้างโค้ดที่เปราะบางและ "วัตถุของพระเจ้า" ได้
  • ไม่เหมาะสมเสมอไป:สำหรับแอปพลิเคชันที่ใช้ข้อมูลจำนวนมากหรือประสิทธิภาพสูง (เช่น เอนจิ้นเกม) การออกแบบที่เน้นข้อมูล อาจมีประสิทธิภาพมากขึ้น

ข้อเสียเหล่านี้จะได้รับการบรรเทาผ่านการใช้รูปแบบการออกแบบอย่างระมัดระวัง หลีกเลี่ยงการสืบทอดที่ไม่จำเป็น และรวม OOP เข้ากับแนวคิดอื่นๆ เช่น การเขียนโปรแกรมเชิงฟังก์ชัน


55) การจัดการหน่วยความจำมีการจัดการแตกต่างกันอย่างไร C++, Javaและ Python?

  • C++:นักพัฒนาจัดการหน่วยความจำด้วยตนเองโดยใช้ new และ delete. ตัวชี้อัจฉริยะ (unique_ptr, shared_ptr) ลดความเสี่ยงการรั่วไหล
  • Java:การเก็บขยะอัตโนมัติจะจัดการการจัดสรรและการยกเลิกการจัดสรร แม้ว่าเวลาจะไม่แน่นอนก็ตาม
  • Python:ใช้การนับอ้างอิงและการเก็บขยะ (การตรวจจับรอบ)
ภาษาที่ใช้ การจัดสรร การจัดสรรคืน
C++ คู่มือ (new) คู่มือ (delete)
Java การจัดสรรฮีป เก็บขยะ
Python พลวัต การนับอ้างอิง + GC

การเข้าใจความแตกต่างเหล่านี้ถือเป็นสิ่งสำคัญในการสัมภาษณ์ เนื่องจากความแตกต่างเหล่านี้สะท้อนถึงการแลกเปลี่ยนระหว่างการควบคุม (C++) และประสิทธิภาพการทำงานของนักพัฒนา (Java, Python).


56) ปัจจัยใดบ้างที่มีอิทธิพลต่อการเลือกใช้วิธีสืบทอดหรืออินเทอร์เฟซ?

การเลือกขึ้นอยู่กับปัจจัยหลายประการ:

  • มรดก:ใช้เมื่อมีความสัมพันธ์ "is-a" ที่แท้จริง และคลาสย่อยจำเป็นต้องใช้การใช้งานพื้นฐานซ้ำ ตัวอย่าง: Dog extends Animal.
  • อินเตอร์เฟซ: ใช้เมื่อหลายคลาสที่ไม่เกี่ยวข้องกันต้องแบ่งปันพฤติกรรม ตัวอย่าง: Bird และ Airplane การดำเนินการ Flyable.
  • ข้อจำกัดทางภาษา: Java รองรับการสืบทอดคลาสเพียงแบบเดียวแต่ให้อินเทอร์เฟซหลายตัวได้
  • เป้าหมายการออกแบบ:สนับสนุนอินเทอร์เฟซสำหรับสัญญาและการเชื่อมโยงแบบหลวมๆ ใช้การสืบทอดสำหรับตรรกะฐานที่นำกลับมาใช้ใหม่ได้

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


57) คุณสามารถให้ตัวอย่างในโลกแห่งความเป็นจริงของการห่อหุ้มในระบบซอฟต์แวร์ได้หรือไม่

ใช่ ซอฟต์แวร์ในโลกแห่งความเป็นจริงใช้การห่อหุ้มอย่างกว้างขวาง:

  • แอปพลิเคชันธนาคาร:ยอดเงินในบัญชีเป็นแบบส่วนตัว เข้าถึงได้เฉพาะผ่าน deposit() or withdraw().
  • API ของเว็บ:จุดสิ้นสุดเปิดเผยเฉพาะการดำเนินการที่จำเป็นเท่านั้น และซ่อนตรรกะของฐานข้อมูลภายใน
  • ไลบรารี/กรอบงาน:นักพัฒนาโต้ตอบกับวิธีการสาธารณะ (เช่น ArrayList.add() in Java) โดยไม่ทราบตรรกะการปรับขนาดอาร์เรย์ภายใน

การห่อหุ้มช่วยให้แน่ใจว่าระบบ ปลอดภัย เป็นโมดูล และปรับเปลี่ยนได้อนุญาตให้มีการเปลี่ยนแปลงภายในโดยไม่กระทบการใช้งานภายนอก ซึ่งสะท้อนถึงแนวปฏิบัติในโลกแห่งความเป็นจริง เช่น การใช้ตู้ ATM ที่ผู้ใช้โต้ตอบด้วยปุ่มต่างๆ แทนที่จะใช้กลไกภายใน


58) เมื่อใดควรเลือกใช้คลาสแบบนามธรรมแทนอินเทอร์เฟซ?

คลาสแบบนามธรรมจะดีกว่าเมื่อ:

  • มี การใช้งานร่วมกัน ที่คลาสย่อยหลายคลาสควรสืบทอดกัน
  • ชั้นเรียนมีความสัมพันธ์แบบลำดับชั้นที่แข็งแกร่งร่วมกัน (เช่น Shape → Circle, Rectangle).
  • จำเป็นต้องมีการเตรียมพร้อมสำหรับอนาคตเพื่อเพิ่มวิธีการที่ไม่ใช่แบบนามธรรมโดยไม่ทำลายคลาสย่อยที่มีอยู่

อินเทอร์เฟซจะดีกว่าเมื่อคลาสไม่เกี่ยวข้องกันแต่ต้องมีพฤติกรรมร่วมกัน ตัวอย่างเช่น: Bird และ Drone ทั้งการนำไปปฏิบัติ Flyable.

ในการสรุป:

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

59) วงจรชีวิตของวัตถุแตกต่างกันอย่างไรในแต่ละภาษา?

  • C++:วงจรชีวิตของวัตถุประกอบด้วยการสร้าง (สแต็กหรือฮีป) การใช้งาน และการทำลาย (แบบชัดเจนหรืออัตโนมัติ) ตัวทำลายล้างจะทำหน้าที่ล้างข้อมูลแบบกำหนดได้
  • Java:วงจรชีวิตของวัตถุรวมถึงการสร้าง (ผ่าน new) การใช้งาน และการเก็บขยะ การทำลายข้อมูลไม่สามารถกำหนดได้ จัดการโดย GC
  • Python:วัตถุจะถูกสร้างขึ้นแบบไดนามิกและถูกทำลายเมื่อจำนวนการอ้างอิงลดลงเหลือศูนย์ GC จัดการรอบ
ภาษาที่ใช้ การสร้าง การทำลายล้าง
C++ นวกรรมิก ตัวทำลายล้าง (กำหนดแน่นอน)
Java new GC (ไม่กำหนดแน่นอน)
Python พลวัต การนับคะแนนผู้ตัดสิน + GC

การทำความเข้าใจวงจรชีวิตเหล่านี้ถือเป็นกุญแจสำคัญในการจัดการทรัพยากรและการเพิ่มประสิทธิภาพระบบ


60) ภาษาสมัยใหม่ผสมผสาน OOP เข้ากับแนวคิดอื่น ๆ ได้อย่างไร

ภาษาต่างๆ ได้รับการสนับสนุนเพิ่มมากขึ้น การเขียนโปรแกรมแบบหลายกระบวนทัศน์ เพื่อเอาชนะข้อจำกัดของ OOP:

  • Java:บูรณาการการเขียนโปรแกรมเชิงฟังก์ชันผ่านการแสดงออกแลมบ์ดาและสตรีม
  • C#:ผสมผสาน OOP กับ LINQ และการเขียนโปรแกรมแบบอะซิงค์
  • Python:ผสมผสาน OOP สไตล์เชิงขั้นตอนและเชิงฟังก์ชันได้อย่างลงตัว

ตัวอย่างใน Java (ฟังก์ชัน + OOP):

List nums = Arrays.asList(1,2,3,4);
nums.stream().map(n -> n * n).forEach(System.out::println);

การผสมผสานนี้ช่วยให้นักพัฒนาสามารถเลือกรูปแบบที่มีประสิทธิภาพสูงสุดสำหรับงานได้ ช่วยเพิ่มประสิทธิภาพการทำงานและความยืดหยุ่น พร้อมทั้งยังคงรักษาข้อดีของ OOP ไว้


🔍 คำถามสัมภาษณ์ OOPS ยอดนิยมพร้อมสถานการณ์จริงและคำตอบเชิงกลยุทธ์

นี่คือ 10 คำถามสัมภาษณ์ OOPS (Object-Oriented Programming System) ที่คัดสรรมาอย่างดี พร้อมคำตอบที่ใช้งานได้จริงและเกี่ยวข้องกับอุตสาหกรรม คำถามเหล่านี้ออกแบบมาเพื่อทดสอบความรู้ทางเทคนิค ความสามารถในการปรับตัวตามพฤติกรรม และการตัดสินใจตามสถานการณ์

1) คุณสามารถอธิบายหลักการหลักสี่ประการของการเขียนโปรแกรมเชิงวัตถุได้หรือไม่

สิ่งที่คาดหวังจากผู้สมัคร: คำอธิบายที่ชัดเจนเกี่ยวกับการห่อหุ้ม การสืบทอด รูปแบบหลายแบบ และการแยกส่วน

ตัวอย่างคำตอบ:

เสาหลักทั้งสี่ของ OOPS ได้แก่ การห่อหุ้ม (encapsulation), การสืบทอด (inheritance), พหุสัณฐาน (polymorphism) และการแยกย่อย (abstraction) การห่อหุ้มจะซ่อนรายละเอียดภายในของอ็อบเจกต์และเปิดเผยเฉพาะสิ่งที่จำเป็น การสืบทอดช่วยให้คลาสสามารถนำโค้ดกลับมาใช้ใหม่และสร้างความสัมพันธ์ได้ พหุสัณฐานช่วยให้อ็อบเจกต์มีพฤติกรรมที่แตกต่างกันไปตามบริบท เช่น การโอเวอร์โหลดเมธอดหรือการโอเวอร์ไรด์ ส่วนการแยกย่อยจะเน้นที่การกำหนดคุณลักษณะสำคัญ พร้อมกับซ่อนรายละเอียดการใช้งาน


2) คุณนำหลักการ OOPS ไปใช้ในบทบาทก่อนหน้านี้เพื่อปรับปรุงความสามารถในการบำรุงรักษาของโครงการอย่างไร

สิ่งที่คาดหวังจากผู้สมัคร: การนำ OOPS ไปใช้งานจริงในโครงการจริง

ตัวอย่างคำตอบ:

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


3) ความแตกต่างระหว่างการจัดองค์ประกอบและการสืบทอดคืออะไร และคุณต้องการแบบไหนมากกว่ากัน?

สิ่งที่คาดหวังจากผู้สมัคร: การคิดวิเคราะห์และความเข้าใจในการแลกเปลี่ยนการออกแบบ

ตัวอย่างคำตอบ:

“การสืบทอดสร้างแบบจำลองความสัมพันธ์แบบ ‘is-a’ ในขณะที่การจัดองค์ประกอบสร้างแบบจำลองความสัมพันธ์แบบ ‘has-a’ ผมชอบการจัดองค์ประกอบมากกว่าเมื่อต้องการรักษาความเชื่อมโยงแบบหลวมๆ และความยืดหยุ่น เพราะมันช่วยให้สามารถเปลี่ยนแปลงแบบไดนามิกได้โดยไม่ส่งผลกระทบต่อคลาสแม่ ยกตัวอย่างเช่น ในตำแหน่งก่อนหน้านี้ ผมได้แทนที่ลำดับชั้นการสืบทอดแบบลึกด้วยการจัดองค์ประกอบในระบบบันทึก ซึ่งช่วยลดความซับซ้อนและปรับปรุงความสามารถในการนำกลับมาใช้ใหม่”


4) คุณจะอธิบายเรื่องความหลากหลายให้กับผู้มีส่วนได้ส่วนเสียที่ไม่ได้มีความรู้ด้านเทคนิคได้อย่างไร

สิ่งที่คาดหวังจากผู้สมัคร: ความสามารถในการลดความซับซ้อนของแนวคิดเพื่อการสื่อสารทางธุรกิจ

ตัวอย่างคำตอบ:

“พหุสัณฐาน (Polymorphism) หมายความว่าฟังก์ชันหนึ่งสามารถทำงานแตกต่างกันได้ขึ้นอยู่กับบริบท ตัวอย่างเช่น ลองนึกถึงคำว่า 'drive' คนเราสามารถขับรถยนต์ เรือ หรือรถบรรทุกได้ แต่แอคชันนั้นยังคงเรียกว่า driving ในซอฟต์แวร์ พหุสัณฐานช่วยให้เราเขียนเมธอดเดียวที่สามารถปรับพฤติกรรมของมันได้ตามวัตถุที่เรียกใช้งาน”


5) คุณอธิบายข้อบกพร่องที่ท้าทายที่คุณเผชิญเกี่ยวกับการออกแบบเชิงวัตถุได้ไหม คุณแก้ไขมันอย่างไร

สิ่งที่คาดหวังจากผู้สมัคร: ทักษะการแก้ปัญหาและแก้ไขจุดบกพร่อง

ตัวอย่างคำตอบ:

ในงานก่อนหน้านี้ของผม เราพบบั๊กในระบบการจัดการสินค้าคงคลังที่เมธอดที่ถูกเขียนทับถูกเรียกใช้งานไม่ถูกต้อง หลังจากแก้ไขบั๊กแล้ว ผมพบว่าปัญหาเกิดจากการใช้ static binding แทน dynamic dispatch ผมจึงปรับโครงสร้างการออกแบบใหม่โดยให้พึ่งพาอินเทอร์เฟซและเมธอดเสมือนที่เหมาะสม ซึ่งช่วยคืนสภาพพฤติกรรมโพลีมอร์ฟิกตามที่คาดหวังไว้และแก้ไขปัญหานี้


6) ลองนึกภาพว่าคุณเข้าร่วมโปรเจกต์ที่มีโค้ดเบสเป็นเชิงขั้นตอนอย่างมาก คุณจะเปลี่ยนมันไปเป็นแบบ OOPS โดยไม่กระทบกับฟังก์ชันการทำงานที่มีอยู่ได้อย่างไร

สิ่งที่คาดหวังจากผู้สมัคร: การคิดเชิงกลยุทธ์และการดำเนินการอย่างรอบคอบ

ตัวอย่างคำตอบ:

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


7) คุณจะสร้างสมดุลระหว่างการออกแบบคลาสเพื่อความยืดหยุ่นสูงสุดกับการรักษาความเรียบง่ายได้อย่างไร

สิ่งที่คาดหวังจากผู้สมัคร: การตัดสินใจและการตระหนักรู้ด้านสถาปัตยกรรม

ตัวอย่างคำตอบ:

ในบทบาทสุดท้ายของผม ผมได้เรียนรู้ว่าการออกแบบที่มากเกินไปอาจสร้างผลเสียมากกว่าผลดี ผมเริ่มต้นด้วยความเรียบง่ายและเพิ่มความยืดหยุ่นเฉพาะเมื่อกรณีการใช้งานต้องการ ตัวอย่างเช่น หากคลาสในอนาคตอันใกล้นี้จำเป็นต้องใช้ส่วนขยายเพียงส่วนเดียว ผมหลีกเลี่ยงการนำเลเยอร์นามธรรมที่ไม่จำเป็นมาใช้ ผมใช้ YAGNI (You Are Going to Need It) เป็นแนวทางในการสร้างสมดุลระหว่างการออกแบบ


8) คุณจะมั่นใจได้อย่างไรว่าการห่อหุ้มได้รับการดูแลรักษาในการตั้งค่าทีมที่มีนักพัฒนาหลายคนทำงานในคลาสเดียวกัน?

สิ่งที่คาดหวังจากผู้สมัคร: การทำงานร่วมกันเป็นทีมและวินัยในการเขียนโค้ด

ตัวอย่างคำตอบ:

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


9) เล่าให้ฉันฟังเกี่ยวกับครั้งหนึ่งที่คุณต้องอธิบายความสำคัญของรูปแบบการออกแบบให้กับทีมที่ไม่คุ้นเคยกับแนวทางปฏิบัติที่ดีที่สุดของ OOPS

สิ่งที่คาดหวังจากผู้สมัคร: ทักษะการสื่อสารและความเป็นผู้นำ

ตัวอย่างคำตอบ:

ในโปรเจ็กต์ก่อนหน้านี้ ผมได้นำเสนอแนวคิดเรื่องรูปแบบการออกแบบ (design pattern) เมื่อทีมกำลังประสบปัญหากับโค้ดที่ซ้ำกันในโมดูลต่างๆ ผมได้อธิบายรูปแบบต่างๆ เช่น Singleton และ Factory ด้วยการเปรียบเทียบง่ายๆ กับสถานการณ์จริง จากนั้นจึงสาธิตให้เห็นว่าการนำรูปแบบเหล่านี้ไปใช้จะช่วยลดความซ้ำซ้อนและปรับปรุงความสามารถในการบำรุงรักษาได้อย่างไร ด้วยการแสดงให้เห็นถึงการพัฒนาโดยตรงในด้านความสามารถในการอ่านและการดีบัก ทีมงานจึงนำแนวทางปฏิบัติเหล่านี้ไปใช้ได้อย่างรวดเร็ว


10) คุณจะออกแบบลำดับชั้นของคลาสสำหรับแอปพลิเคชันการแชร์รถด้วยยานพาหนะ เช่น รถยนต์ จักรยาน และสกู๊ตเตอร์ ได้อย่างไร

สิ่งที่คาดหวังจากผู้สมัคร: การประยุกต์ใช้งานการออกแบบ OOPS ในทางปฏิบัติ

ตัวอย่างคำตอบ:

ผมจะเริ่มต้นด้วยคลาสฐานแบบนามธรรม 'Vehicle' ที่มีแอตทริบิวต์ร่วมกัน เช่น ID, ความจุ และความเร็ว รวมถึงเมธอดต่างๆ เช่น startRide() และ stopRide() รถยนต์ จักรยาน และสกู๊ตเตอร์จะขยายคลาสนี้และแทนที่เมธอดเมื่อจำเป็น เพื่อให้มั่นใจถึงความสามารถในการปรับขนาด ผมจะใช้อินเทอร์เฟซสำหรับฟีเจอร์ต่างๆ เช่น 'ElectricPowered' หรือ 'FuelPowered' เพื่อแยกข้อกังวลต่างๆ การออกแบบนี้จะรองรับการเพิ่มประเภทยานพาหนะใหม่ๆ โดยไม่ต้องเปลี่ยนแปลงอะไรมากนัก


สรุปโพสต์นี้ด้วย: