ส่วนต่อประสานกับบทคัดย่อระดับ (OO ทั่วไป)


1413

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

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

อินเตอร์เฟซ:

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

ระดับนามธรรม:

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

  1. หลังจากนั้นผู้สัมภาษณ์ถามคำถามว่า "จะเกิดอะไรขึ้นถ้าคุณมีคลาสนามธรรมด้วยวิธีนามธรรมเท่านั้น? สิ่งนั้นจะแตกต่างจากอินเทอร์เฟซอย่างไร" ฉันไม่รู้คำตอบ แต่ฉันคิดว่านี่เป็นมรดกตามที่กล่าวไว้ข้างต้นใช่ไหม

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

ดูเพิ่มเติมที่ :


412
ในขณะที่ฉันคิดว่ามันเป็นสิ่งสำคัญที่จะต้องทราบความแตกต่างระหว่างทั้งสองนี้ไม่ใช่คำถามสัมภาษณ์ที่ดี imo นอกเสียจากว่างานจะเขียนหนังสือในหัวข้อ OO คุณดีกว่าที่จะไม่ทำงานกับค้างคาว ding เหล่านั้น
อลัน

107
@ อลัน: ฉันชอบคำถามนี้เป็นคำถามสัมภาษณ์ แต่ฉันจะไม่พูดถึงใครซักคนเกี่ยวกับเรื่องนี้ - ฉันอาจโพสต์มันมากขึ้นเช่น "คุณจะเลือกอินเทอร์เฟซสำหรับคลาสพื้นฐานที่เป็นนามธรรมเมื่อใด "หรือบางอย่างที่คล้ายกัน
Reed Copsey

11
บางทีพวกเขาอาจจะเป็นคำตอบที่เน้นการออกแบบมากกว่า ... แต่เหมือนคุณฉันจะถือว่ามันเป็นคำถามทางเทคนิค
CurtainDog

16
ความแตกต่างของตารางดีที่นี่: mindprod.com/jgloss/interfacevsabstract.html
Rajat_R

30
@Kave: I insisted you can't have a public variable inside an interface.ฉันคิดว่าส่วนต่อประสานสามารถมีตัวแปรสาธารณะได้ ในความเป็นจริงตัวแปรในอินเทอร์เฟซจะเปิดเผยโดยอัตโนมัติและสุดท้าย
ผู้เรียน

คำตอบ:


746

ในขณะที่คำถามของคุณระบุว่าเป็นของ "General OO" ดูเหมือนว่าจะเน้นไปที่การใช้. NET ของคำเหล่านี้

ใน. NET (คล้ายกับ Java):

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

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

แท้จริงแล้วมีสำนวน C ++ ที่เรียกว่า Non-Virtual Interface (NVI) ซึ่งวิธีการสาธารณะเป็นวิธีการที่ไม่ใช่เสมือนที่ 'thunk' เป็นวิธีเสมือนส่วนตัว:


7
ขอบคุณ. ฉันคิดว่าเนื่องจากคำตอบของคุณกล่าวถึง + ภาพรวมที่ดีของส่วนที่เหลือทั้งหมดฉันทำเครื่องหมายคำตอบของคุณเป็นคำตอบสุดท้าย คุณพูดถูกฉันขอ OO ทั่วไปเนื่องจากผู้สัมภาษณ์คนแรกขอ OO ทั่วไป แต่เนื่องจากฉันเป็น C # ฉันมักจะลืมไป ;-) ขอบคุณสำหรับคำอธิบาย C ++ เช่นเดียวกับ c ++ ที่น่าเหลือเชื่อ
Houman

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

82
+1: ฉันยินดีที่จะเดิมพันว่าลิงที่เป็นเจ้าภาพการสัมภาษณ์ไม่ได้ตระหนักว่าภาษาอื่นใช้ OO ต่างกัน
การแข่งขัน Lightness ใน Orbit

2
@JL ฉันไม่เห็นว่าปัญหาอยู่ที่ใด คุณดูเหมือนจะมีวิธีการที่เป็นนามธรรมสับสนกับระดับนามธรรม วิธีนามธรรมไม่มีการใช้งาน แต่ภายในของนามธรรมชั้น , บางวิธีอาจเป็นนามธรรม (คือไม่มีการดำเนินการ) ในขณะที่บางคนอื่น ๆ แน่นอนจะมีการดำเนินการ
xji

19
โปรดทราบว่าใน Java 8 คุณสามารถมีวิธีการเริ่มต้นและวิธีการคงที่ในส่วนต่อประสานซึ่งหมายความว่าส่วนต่อประสาน Java สามารถมีการใช้งาน อ้างอิงที่นี่ เห็นได้ชัดว่าคุณอ้างถึง NET เป็นหลักดังนั้นนี่เป็นเพียงข้อสังเกตที่อ้างอิงถึง Java
davtom

866

การเปรียบเทียบ: เมื่อฉันอยู่ในกองทัพอากาศฉันไปฝึกอบรมนักบินและกลายเป็นนักบิน USAF (กองทัพอากาศสหรัฐ) ณ จุดนี้ฉันไม่ได้มีคุณสมบัติที่จะบินอะไรและต้องเข้าร่วมการฝึกอบรมประเภทเครื่องบิน เมื่อฉันผ่านการรับรองฉันเป็นนักบิน (ระดับนามธรรม) และนักบิน C-141 (ระดับคอนกรีต) หนึ่งในงานที่มอบหมายของฉันฉันได้รับหน้าที่เพิ่มเติม: เจ้าหน้าที่ความปลอดภัย ตอนนี้ฉันยังเป็นนักบินและนักบิน C-141 แต่ฉันก็ทำหน้าที่เจ้าหน้าที่ความปลอดภัยด้วย (ฉันใช้งาน ISafetyOfficer เพื่อพูด) นักบินไม่จำเป็นต้องเป็นเจ้าหน้าที่ความปลอดภัยคนอื่น ๆ ก็สามารถทำได้เช่นกัน

นักบิน USAF ทุกคนจะต้องปฏิบัติตามกฎเกณฑ์กว้างของกองทัพอากาศและนักบิน C-141 (หรือ F-16 หรือ T-38) เป็นนักบิน USAF ทุกคนสามารถเป็นเจ้าหน้าที่ความปลอดภัย ดังนั้นเพื่อสรุป:

  • นักบิน: ระดับนามธรรม
  • C-141 Pilot: คลาสคอนกรีต
  • เจ้าหน้าที่ความปลอดภัย: อินเทอร์เฟซ

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


87
ฉันชอบการเปรียบเทียบนี้จริง ๆ มันใช้ตัวอย่างง่าย ๆ ในการอธิบายหัวข้อที่ซับซ้อนเล็กน้อย
Kevin Bowersox

13
นี่เป็นวิธีที่ดีที่สุดในการเข้าใจคำศัพท์ OO ที่ซับซ้อน ในระยะสั้นทฤษฎีทั้งหมดมีค่าเฉพาะเมื่อคุณสามารถใช้ประโยชน์ได้จริง @Jay คุณ rexample เป็นเรื่องง่ายที่จะเข้าใจแล้วสัญลักษณ์แสดงหัวข้อย่อยหลาย ๆ จุด (ส่วนใหญ่เจาะจิตใจแทนการถูกดูดซึม!)
vs

54
ฉันยังสับสนอยู่ สมมติว่าคุณได้รับคุณสมบัติ F-16 และ T-38 ดังนั้นตอนนี้คลาสJayไม่สามารถสืบทอดจากหลายคลาส (นักบิน C-141, นักบิน F-16 และนักบิน T-38) นั่นหมายความว่าคลาสของพวกเขาควรจะกลายเป็นอินเทอร์เฟซ? ขอบคุณ
อเล็กซ์ Okrushko

37
ผู้คนจำนวนมากให้ความเห็น +1 กับ Alex อย่างถูกต้องเนื่องจากมันแสดงให้เห็นถึงความอ่อนแอในตัวอย่างนี้ อันดับแรกฉันจะบอกว่าเจย์จะเป็นตัวอย่างของ C-141Pilot แทนที่จะเป็นคลาสของตัวเอง นอกจากนี้เนื่องจากใน USAF 99% ของนักบินทุกคนมีคุณสมบัติเฉพาะในเครื่องบินหนึ่งเครื่องต่อครั้ง (FCF และนักบินทดสอบที่มีข้อยกเว้นที่น่าทึ่ง) ฉันไม่ได้พิจารณาคุณสมบัติที่หลากหลายและวิธีการที่จะนำไปใช้ อย่างที่ฉันรู้นักบินคนหนึ่งเมื่อ 50 ปีก่อนมีคุณสมบัติในเครื่องบินต่าง ๆ 25 ลำพร้อมกันฉันคิดว่ามันเป็นตัวอย่างว่าเราไม่ต้องการใช้มรดกหลายอย่างอย่างไร
Jay

20
เนื่องจากไม่น่าเป็นไปได้ที่นักบินคนหนึ่งจะบินเครื่องบินมากกว่าหนึ่งลำในเวลาเดียวกันมันจะเป็นโอกาสที่ดีในการใช้รูปแบบกลยุทธ์ นักบินจะมีชุดของใบรับรองและเลือกที่ถูกต้องในขณะทำงาน การรับรองจะถูกเข้ารหัสเป็นพฤติกรรมที่จะใช้อินเทอร์เฟซ IFlyPlane ด้วยวิธี TakeOff, Land, Eject
Michael Blackburn

221

ฉันคิดว่าคำตอบที่ต้องการคือความแตกต่างทางปรัชญาพื้นฐานหรือ OPPS

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

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

สำหรับเช่น รถยนต์และรถบรรทุกมีคุณสมบัติหลักและพฤติกรรมของคลาสนามธรรมของรถยนต์เป็นจำนวนมาก แต่พวกเขาก็มีพฤติกรรมที่เกี่ยวข้องกับอุปกรณ์ต่อพ่วงเช่นสร้างไอเสียซึ่งแม้แต่รถยนต์ที่ไม่ใช่รถยนต์เช่น Drillers หรือ PowerGenerators ก็ไม่จำเป็นต้องกำหนดรถยนต์หรือรถบรรทุก ดังนั้นรถยนต์, รถบรรทุก, Driller และ PowerGenerator จึงสามารถแบ่งปันอินเทอร์เฟซเดียวกันได้ทั้งหมด


32
ฉันคิดว่าการเปรียบเทียบที่ดียิ่งขึ้นจะเป็น "useFuel" ซึ่งจะแสดงลักษณะสัญญาของอินเทอร์เฟซ
Pureferret

@Pureferret หากaccelerateเป็นส่วนหนึ่งของพฤติกรรมหลักของคลาสนามธรรมรถยนต์แล้วฉันไม่สามารถพูดได้accelerateแสดงให้เห็นถึงลักษณะสัญญา ลักษณะสัญญาคืออะไร? ทำไมคำนี้contractแนะนำเมื่อใดก็ตามที่เราพูดถึงinterface?
แลกเปลี่ยน

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

1
@Pureferret ฉันยกแบบสอบถามที่ลิงค์เดียวกัน
overexchange

1
@Pureferret หากinterfaceจำเป็นต้องมีพฤติกรรมต่อพ่วงแล้วทำไมpublic interface List<E> extends Collection<E> {}ถูกออกแบบมาเพื่ออธิบายพฤติกรรมหลักของlist? นี่เป็นคำตอบที่ขัดแย้งกันจริงของ prasun ทั้งสองCollection<E>และList<E>อินเทอร์เฟซที่นี่
แลกเปลี่ยน

198

สั้น: คลาสนามธรรมถูกใช้สำหรับการสร้างแบบจำลองลำดับชั้นของคลาสที่มีลักษณะคล้ายกัน (ตัวอย่างเช่นสัตว์สามารถเป็นคลาสนามธรรมและมนุษย์, Lion, Tiger สามารถเป็นคลาสที่ได้จากคอนกรีต)

และ

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


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

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

2
@dhananjay: ฉันเห็นว่า Height สามารถแยกออกจากแนวคิดของ Animal class และสามารถมาจาก class ที่แตกต่างกันได้ แต่คุณหมายถึงอะไรโดย "การสื่อสาร" ระหว่างชั้นเรียน? มันเป็นเพียงการกำหนดความสูงสำหรับชั้นเรียนของตัวเองถูกต้องหรือไม่
TTT

77

มีความแตกต่างอื่น ๆ สองสามอย่าง -

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

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

บทคัดย่อคลาสพื้นฐานสามารถแก้ไขได้ใน v2 + โดยไม่ทำลาย API การเปลี่ยนแปลงอินเทอร์เฟซกำลังทำลายการเปลี่ยนแปลง

[C # /. NET เฉพาะ] การเชื่อมต่อซึ่งแตกต่างจากคลาสฐานนามธรรมสามารถนำไปใช้กับประเภทค่า (structs) โครงสร้างไม่สามารถสืบทอดจากคลาสพื้นฐานที่เป็นนามธรรมได้ สิ่งนี้อนุญาตให้นำไปใช้กับประเภทของมูลค่า


5
+1 สำหรับจุดสำคัญที่สามารถใช้อินเตอร์เฟซมากกว่าหนึ่งรายการในคลาส
cgp

นั่นเป็นข้อได้เปรียบที่แท้จริงอย่างหนึ่งของอินเทอร์เฟซมากกว่าคลาสฐานนามธรรม IMO มิฉะนั้นผมเห็นด้วยกับแนวทางการออกแบบ .NET ที่ว่าตอนนี้พูดกับ "ชอบฐานเรียนนามธรรมมากกว่าอินเตอร์เฟซ"
กก Copsey

ถึงแม้ว่ามันจะแหลมถ้าคุณสามารถเพิ่มจุดที่มันยังอินเทอร์เฟซสามารถใช้กับคลาสใดก็ได้
cgp

1
@altCognito: คิดว่าเป็นประเภทที่มีการจัดการกับวรรคสอง สิ่งนี้ทำให้ฉันนึกถึงว่าอินเทอร์เฟซนั้นทำงานกับประเภทของค่าดังนั้นฉันจึงเพิ่มมัน
Reed Copsey

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

68

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

public class Vehicle {
    private Driver driver;
    private Seat[] seatArray; //In java and most of the Object Oriented Programming(OOP) languages, square brackets are used to denote arrays(Collections).
    //You can define as many properties as you want here ...
}

ตอนนี้จักรยาน ...

public class Bicycle extends Vehicle {
    //You define properties which are unique to bicycles here ...
    private Pedal pedal;
}

และรถยนต์ ...

public class Car extends Vehicle {
    private Engine engine;
    private Door[] doors;
}

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

คลาสนามธรรม

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

//......Code of Vehicle Class
abstract public void drive();
//.....Code continues

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

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

public interface Dialable {
    public void dial(Number n);
}

ที่นี่ผู้สร้าง Dialable กำหนดวิธีการโทรออกด้วยหมายเลข คุณเพียงแค่ต้องให้หมายเลขเพื่อโทร

// Makers define how exactly dialable work inside.

Dialable PHONE1 = new Dialable() {
    public void dial(Number n) {
        //Do the phone1's own way to dial a number
    }
}

Dialable PHONE2 = new Dialable() {
    public void dial(Number n) {
        //Do the phone2's own way to dial a number
    }
}


//Suppose there is a function written by someone else, which expects a Dialable
......
public static void main(String[] args) {
    Dialable myDialable = SomeLibrary.PHONE1;
    SomeOtherLibrary.doSomethingUsingADialable(myDialable);
}
.....

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

และที่สำคัญถ้าวันหนึ่งคุณสลับ Dialable ด้วยอันอื่น

......
public static void main(String[] args) {
    Dialable myDialable = SomeLibrary.PHONE2; // <-- changed from PHONE1 to PHONE2
    SomeOtherLibrary.doSomethingUsingADialable(myDialable);
}
.....

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

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

ข้อมูลเพิ่มเติม คลาสที่เป็นนามธรรม vs การเชื่อมต่อ


ไม่เป็นความจริงว่า "ส่วนต่อประสานไม่มีคุณสมบัติใด ๆ "
Bigeyes

@Bigeyes, java ไม่อนุญาตคุณสมบัติในส่วนต่อประสาน ฉันคิดว่ามันเหมือนกันในภาษาอื่นด้วย คุณช่วยอธิบายเพิ่มเติมได้ไหม
fz_salam

ฉันหมายถึง C # /. สุทธิ โปรดดูตัวอย่าง
Bigeyes

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

@happycoder: อีกครั้ง: "ที่นี่โดยใช้อินเทอร์เฟซแทนคลาสนามธรรมคุณไม่จำเป็นต้องกังวลเกี่ยวกับคุณสมบัติของมัน Ex: มันมีหน้าจอสัมผัสหรือแป้นกดหมายเลขมันเป็นโทรศัพท์พื้นฐานหรือโทรศัพท์มือถือคุณแค่ต้อง รู้ว่ามันสามารถหมุนได้หรือไม่นั้นจะสืบทอด (หรือนำไปใช้) อินเตอร์เฟสที่สามารถหมุนได้ " - คุณสามารถแสดงนี้ในตัวอย่างรหัสยังไม่เห็นว่ามันจะได้รับมรดก ...
TTT

45

หากคุณพิจารณาjavaว่าเป็นภาษา OOP เพื่อตอบคำถามนี้ Java 8 release ทำให้เนื้อหาบางส่วนในคำตอบข้างต้นล้าสมัย ตอนนี้อินเตอร์เฟส Java สามารถมีวิธีการเริ่มต้นด้วยการใช้งานที่เป็นรูปธรรม

เว็บไซต์ Oracle ให้ความแตกต่างที่สำคัญระหว่างinterfaceและabstractคลาส

พิจารณาใช้คลาสนามธรรมหาก:

  1. คุณต้องการแบ่งปันรหัสระหว่างคลาสที่เกี่ยวข้องอย่างใกล้ชิดหลายชั้น
  2. คุณคาดหวังว่าคลาสที่ขยายคลาส abstract ของคุณมีวิธีหรือฟิลด์ทั่วไปจำนวนมากหรือต้องการตัวดัดแปลงการเข้าถึงอื่นนอกเหนือจากสาธารณะ (เช่นได้รับการป้องกันและส่วนตัว)
  3. คุณต้องการประกาศเขตข้อมูลไม่คงที่หรือไม่ใช่เขตข้อมูลสุดท้าย

พิจารณาใช้อินเตอร์เฟสหาก:

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

ในแง่ง่ายฉันต้องการที่จะใช้

อินเทอร์เฟซ:การใช้สัญญาโดยวัตถุที่ไม่เกี่ยวข้องหลายรายการ

ระดับนามธรรม:เพื่อใช้พฤติกรรมที่เหมือนกันหรือแตกต่างระหว่างวัตถุที่เกี่ยวข้องหลายรายการ

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


33

ผู้สัมภาษณ์กำลังเห่าต้นไม้ประหลาด สำหรับภาษาเช่น C # และ Java มีความแตกต่าง แต่ในภาษาอื่นเช่น C ++ นั้นไม่มี ทฤษฎี OO ไม่ได้แยกความแตกต่างของทั้งสอง แต่เพียงไวยากรณ์ของภาษา

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

ใน C # หรือ Java คลาสนามธรรมโดยไม่มีการใช้งานจะแตกต่างจากอินเตอร์เฟสในไวยากรณ์ที่ใช้ในการสืบทอดจากมันและความจริงที่ว่าคุณสามารถสืบทอดจากหนึ่ง


ฉันถูกถามคำถามเดียวกันเมื่อสัปดาห์ที่แล้วฉันไม่มีประสบการณ์กับ Java แต่ฉันทำงานกับ C ++ มาระยะหนึ่งแล้ว ผู้สัมภาษณ์ไม่ได้ระบุภาษาก่อนถามคำถามดังนั้นฉันเพิ่งอธิบายว่าอินเทอร์เฟซในกรณีนี้เป็นคลาสแบบนามธรรมโดยไม่มีสถานะหรือการใช้งานใด ๆ ฉันเห็นด้วยว่ามันเป็นคำถามแปลก ๆ เช่นกัน
dacabdi

31

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


17
อินเทอร์เฟซบรรลุ IMO ความสัมพันธ์ "Acts-as-a" มากขึ้น การห่อหุ้มให้ได้องค์ประกอบที่ดีกว่าอินเทอร์เฟซ
Reed Copsey

12
ฉันไม่คิดว่าการใช้อินเทอร์เฟซจะอยู่ภายใต้องค์ประกอบ
Pavan Dittakavi

นอกจากนี้อินเทอร์เฟซมีแนวโน้มที่จะใช้เพื่ออธิบาย "ความสามารถ" เช่น IDisposable มันใช้เพื่อแบ่งปันฟังก์ชั่นระหว่างคลาสที่คลาสเหล่านี้ "สามารถทำ" บางสิ่งบางอย่าง ตัวอย่างอื่น ๆ IFlyable สามารถใช้งานได้กับนกและเครื่องบิน แต่เบิร์ดอาจได้มาจากสิ่งมีชีวิตคลาสที่ airecraft นั้นได้มาจาก AirCraft
Peter.Wang

26

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

  1. เมื่อใดที่เราควรใช้ส่วนต่อประสาน

    หากคุณไม่ทราบเกี่ยวกับการใช้งานเพียงแค่เรามีสเปคความต้องการแล้วเราก็ไปกับอินเตอร์เฟส

  2. เมื่อใดที่เราควรใช้คลาสนามธรรม?

    หากคุณรู้จักการนำไปใช้ แต่ไม่สมบูรณ์ (นำไปใช้บางส่วน) เราจะไปกับคลาสนามธรรม

    อินเตอร์เฟซ

    ทุกวิธีโดยนามธรรมสาธารณะเริ่มต้นหมายถึงอินเตอร์เฟซเป็นนามธรรมแท้ 100%

    นามธรรม

    สามารถมีวิธีคอนกรีตและวิธีนามธรรม, วิธีคอนกรีตคืออะไร, ซึ่งมีการใช้งานในระดับนามธรรม, ระดับนามธรรมเป็นชั้นที่มีการประกาศนามธรรม - มันอาจหรืออาจจะไม่รวมถึงวิธีนามธรรม

    อินเตอร์เฟซ

    เราไม่สามารถประกาศอินเตอร์เฟสเป็นส่วนตัวได้รับการคุ้มครอง

    ถาม: ทำไมเราไม่ประกาศอินเทอร์เฟซส่วนตัวและได้รับการป้องกัน

    เพราะโดยวิธีการเริ่มต้นอินเตอร์เฟซเป็นนามธรรมสาธารณะดังนั้นเหตุผลที่เราไม่ได้ประกาศอินเตอร์เฟซที่เป็นส่วนตัวและได้รับการคุ้มครอง

    วิธีการเชื่อมต่อ
    เราไม่สามารถประกาศว่าอินเทอร์เฟซเป็นส่วนตัวได้รับการป้องกันขั้นสุดท้ายคงที่ซิงโครไนซ์ดั้งเดิม .....

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

    นามธรรม

    เรามีความสุขที่จะใช้กับสาธารณะคงที่ส่วนตัวสุดท้ายสุดท้าย .... หมายความว่าไม่มีข้อ จำกัด ในนามธรรม

    อินเตอร์เฟซ

    ตัวแปรถูกประกาศในส่วนต่อประสานโดยเป็นค่าเริ่มต้นคงที่สาธารณะสุดท้ายดังนั้นเราจึงไม่ได้ประกาศตัวแปรเป็นส่วนตัวได้รับการคุ้มครอง

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

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

    นามธรรม

    ตัวแปรบทคัดย่อไม่จำเป็นต้องประกาศสแตติกสาธารณะสุดท้าย

ฉันหวังว่าบทความนี้มีประโยชน์


4
ฉันไม่เห็นด้วยกับประเด็นนี้: Abstract class must have at lease one abstract method.เป็นไปได้ที่จะมีคลาส Abstract โดยไม่มีเมธอด Abstract ตราบใดที่คุณใช้มัน การอ้างอิง: An abstract class is a class that is declared abstract—it may or may not include abstract methods.แหล่งอ้างอิง: docs.oracle.com/javase/tutorial/java/IandI/abstract.html
Devner

คุณกำลังพูดถึงรายละเอียดทางเทคนิคและการนำไปใช้คุณไม่ได้ตอบคำถามในแง่ของ OOP ทั่วไป
Billal Begueradj

26

แนวคิดการพูดการใช้ภาษากฎระเบียบประโยชน์และการบรรลุเป้าหมายการเขียนโปรแกรมโดยใช้ใครก็ได้หรือทั้งสองอย่างสามารถหรือไม่สามารถมีรหัส / ข้อมูล / ทรัพย์สิน blah blah มรดกเดียวหรือหลายอย่างนอกเหนือ

1- บทคัดย่อ (หรือนามธรรมที่บริสุทธิ์) คลาสหมายถึงการใช้ลำดับชั้น หากวัตถุธุรกิจของคุณมีลักษณะค่อนข้างคล้ายโครงสร้างแสดงถึงความสัมพันธ์แบบ parent-child (ลำดับชั้น) เท่านั้นดังนั้นคลาสการสืบทอด / บทคัดย่อจะถูกใช้ หากรูปแบบธุรกิจของคุณไม่มีลำดับชั้นก็ไม่ควรใช้การสืบทอด (ที่นี่ฉันไม่ได้พูดถึงตรรกะการเขียนโปรแกรมเช่นรูปแบบการออกแบบบางอย่างต้องมีการสืบทอด) แนวคิดคลาสนามธรรมเป็นวิธีการใช้ลำดับชั้นของโมเดลธุรกิจใน OOP มันไม่มีอะไรเกี่ยวข้องกับอินเตอร์เฟซจริง ๆ แล้วการเปรียบเทียบคลาสนามธรรมกับอินเทอร์เฟซนั้นไม่มีความหมายเพราะทั้งสองเป็นแนวคิดที่แตกต่างกันโดยสิ้นเชิง มันถูกถามในการสัมภาษณ์เพียงเพื่อตรวจสอบแนวคิดเพราะทั้งสองฟังก์ชั่นให้ค่อนข้างเหมือนกันเมื่อมีการใช้งานและเรามักจะเน้นการเขียนโปรแกรมมากขึ้น [จำไว้ในใจเช่นกันว่า Abstraction นั้นแตกต่างจาก Abstract Class]

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

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

เมื่อคุณถูกถามเกี่ยวกับความแตกต่างจริง ๆ แล้วมันเป็นความแตกต่างทางแนวคิดไม่ใช่ความแตกต่างในการใช้งานเฉพาะภาษาเว้นแต่จะถามอย่างชัดเจน

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

ถ้าคุณมีคลาสนามธรรมด้วยวิธีนามธรรมเท่านั้น?


นั่นเป็นผลรวมของคำตอบสำหรับคำถามนี้ค่อนข้างดี
pranavn

ฟังก์ชั่นการใช้งานกับโครงสร้างขยายตัวดี!
harshvchawla

21

สำหรับ. Net

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

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


2
ใช่ สถานะ! นั่นคือสิ่งที่ผู้สัมภาษณ์คนที่สองมีความหมายด้วยวิธีแปลก ๆ ในการพูดว่า "ตัวแปรสาธารณะ" ในส่วนต่อประสาน เอ้ย! คลาสนามธรรมสามารถมีสถานะอินเตอร์เฟสไม่ได้! และใช่คนอื่น ๆ เห็นด้วยกับความแตกต่างระหว่างวิธีการสืบทอดของพวกเขาเช่นกันซึ่งฉันลืมที่จะพูดถึง แต่คิดออกแล้วในภายหลัง :) ขอบคุณทุกคน!
Houman

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

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

เมื่อคุณสร้างอินสแตนซ์ของคลาสที่กำหนดขึ้นเพื่อใช้งานอินเทอร์เฟซไม่ใช่ "อินสแตนซ์" ของอินเทอร์เฟซนั้นไวยากรณ์ทั้งหมดไม่ทำให้คอมไพเลอร์ตรวจสอบรหัสสำหรับคลาสและตรวจสอบให้แน่ใจว่าพฤติกรรมทุกอย่าง , event, eventHandler, ฯลฯ ) ซึ่งถูกกำหนดโดยอินเตอร์เฟสได้ถูกนำไปใช้ในโค้ดสำหรับคลาส
Charles Bretana

20

ควรใช้ Interface : หากคุณต้องการบอกเป็นนัยถึงกฎเกณฑ์เกี่ยวกับส่วนประกอบที่อาจเกี่ยวข้องหรือไม่เกี่ยวข้องกัน

ข้อดี:

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

จุดด้อย:

  1. จะต้องปฏิบัติตามสัญญาทั้งหมดที่กำหนดไว้
  2. ไม่สามารถมีตัวแปรหรือผู้รับมอบสิทธิ์
  3. เมื่อกำหนดไม่สามารถเปลี่ยนแปลงได้โดยไม่ทำลายทุกชั้นเรียน

บทคัดย่อระดับ : ควรใช้ในที่ที่คุณต้องการมีพฤติกรรมพื้นฐานหรือเริ่มต้นบางอย่างหรือการใช้งานสำหรับส่วนประกอบที่เกี่ยวข้องกัน

ข้อดี:

  1. เร็วกว่าอินเตอร์เฟส
  2. มีความยืดหยุ่นในการใช้งาน (คุณสามารถใช้งานได้ทั้งหมดหรือบางส่วน)
  3. สามารถเปลี่ยนแปลงได้ง่ายโดยไม่ทำลายคลาสที่ได้รับ

จุดด้อย:

  1. ไม่สามารถสร้างอินสแตนซ์ได้
  2. ไม่รองรับการสืบทอดหลายแบบ

กำหนดได้เร็วขึ้น มันสำคัญหรือไม่ มันหมายถึงอะไร? opcode สำหรับการเรียกใช้ฟังก์ชันในคลาสนามธรรมนั้นเร็วกว่า opcode สำหรับการเรียกใช้ฟังก์ชันในอินเทอร์เฟซหรือไม่?
denis631

@ denis631 คลาสนามธรรมนั้นเร็วกว่าอินเทอร์เฟซเล็กน้อยเนื่องจากการค้นหาและการโทรนั้นเกี่ยวข้องกับวิธีการอินเทอร์เฟซ อ่านcoderanch.com/t/503450/java/abstract-class-faster-interface
bourax webmaster

17

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

อินเตอร์เฟส:ใช้เพื่อรับรองสัญญาและสร้างการเชื่อมต่อต่ำระหว่างคลาสเพื่อให้แอปพลิเคชั่นบำรุงรักษาปรับขนาดได้และทดสอบได้มากขึ้น

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

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


13
After all that, the interviewer came up with the question "What if you had an 
Abstract class with only abstract methods? How would that be different
from an interface?" 

เอกสารกล่าวอย่างชัดเจนว่าหากคลาสนามธรรมมีการประกาศเมธอดแบบนามธรรมเท่านั้นควรประกาศเป็นอินเทอร์เฟซแทน

An another interviewer asked me what if you had a Public variable inside
the interface, how would that be different than in Abstract Class?

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

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


13
  1. อินเตอร์เฟซ:
    • เราไม่ใช้วิธีการ (หรือกำหนด) เราทำในชั้นเรียนที่ได้รับ
    • เราไม่ประกาศตัวแปรสมาชิกในส่วนต่อประสาน
    • อินเตอร์เฟสแสดงความสัมพันธ์ของ HAS-A นั่นหมายความว่าพวกเขาเป็นหน้ากากของวัตถุ
  2. ระดับนามธรรม:
    • เราสามารถประกาศและกำหนดวิธีการในระดับนามธรรม
    • เราซ่อนสิ่งก่อสร้างของมัน นั่นหมายความว่าจะไม่มีการสร้างวัตถุจากมันโดยตรง
    • คลาสนามธรรมสามารถเก็บตัวแปรสมาชิก
    • คลาสที่ได้รับสืบทอดมาเป็นคลาสนามธรรมซึ่งหมายความว่าวัตถุจากคลาสที่ได้รับมาไม่ถูกปิดบัง แต่สืบทอดไปเป็นคลาสนามธรรม ความสัมพันธ์ในกรณีนี้คือ IS-A

นี่คือความคิดเห็นของฉัน.


12

คัดลอกจาก CLR ผ่าน C # โดย Jeffrey Richter ...

ฉันมักจะได้ยินคำถาม“ ฉันควรออกแบบประเภทฐานหรืออินเตอร์เฟซ?” คำตอบนั้นไม่ชัดเจนเสมอไป

นี่คือแนวทางบางส่วนที่อาจช่วยคุณได้:

■■ความสัมพันธ์ระหว่าง IS-A กับ CAN-DO ประเภทสามารถสืบทอดการใช้งานเพียงครั้งเดียว หากประเภทที่ได้รับไม่สามารถอ้างสิทธิ์ความสัมพันธ์ IS-A กับประเภทฐานได้อย่าใช้ประเภทฐาน ใช้อินเตอร์เฟซ การเชื่อมต่อหมายถึงความสัมพันธ์ที่สามารถทำได้ หากฟังก์ชั่น CAN-DO ดูเหมือนจะอยู่ในประเภทวัตถุต่าง ๆ ให้ใช้ส่วนต่อประสาน ตัวอย่างเช่นชนิดสามารถแปลงอินสแตนซ์ของตัวเองเป็นประเภทอื่น (IConvertible) ชนิดสามารถทำให้เป็นอินสแตนซ์ของตัวเอง (ISerializable) เป็นต้นโปรดทราบว่าประเภทค่าต้องมาจาก System.ValueType ดังนั้นจึงไม่สามารถรับได้ จากคลาสฐานโดยพลการ ในกรณีนี้คุณต้องใช้ความสัมพันธ์ CAN-DO และกำหนดอินเทอร์เฟซ

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

■■การใช้งานที่สอดคล้องไม่ว่าเอกสารสัญญาอินเทอร์เฟซจะดีแค่ไหนก็ไม่น่าเป็นไปได้มากที่ทุกคนจะปฏิบัติตามสัญญาอย่างถูกต้อง 100 เปอร์เซ็นต์ ในความเป็นจริง COM ทนทุกข์ทรมานจากปัญหานี้มากซึ่งเป็นสาเหตุที่วัตถุ COM บางชิ้นทำงานอย่างถูกต้องเฉพาะกับ Microsoft Word หรือ Windows Internet Explorer ด้วยการจัดเตรียมประเภทฐานพร้อมกับการใช้งานเริ่มต้นที่ดีคุณจะเริ่มต้นใช้งานประเภทที่ใช้งานได้และได้รับการทดสอบอย่างดี จากนั้นคุณสามารถปรับเปลี่ยนส่วนต่าง ๆ ที่ต้องการแก้ไข

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


1
@ AbdullahShoaib เป็น - และทุกคนสามารถทำได้ แต่ไม่สามารถทำได้มีความแตกต่างที่นี่ นี่คือเหตุผลพื้นฐานที่เราต้องการส่วนต่อประสาน พฤติกรรมที่ต้องทำจะเป็นส่วนหนึ่งของabstract classเช่นกัน
แลกเปลี่ยน

10

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

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

C # ไม่อนุญาตให้สืบทอดอินเทอร์เฟซเช่นกันโปรดทราบ


1
การใช้คำในแนวนอนและแนวตั้งทำให้มันชัดเจนมากที่จะจินตนาการถึงความแตกต่าง
อินฟินิตี้

10

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

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

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

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

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


10

ในขณะที่คุณอาจจะได้มีความรู้ทางทฤษฎีจากผู้เชี่ยวชาญผมไม่ได้ใช้คำพูดมากในการทำซ้ำทุกคนที่นี่ค่อนข้างให้ฉันอธิบายด้วยตัวอย่างง่ายๆที่เราสามารถใช้ / ไม่สามารถใช้และInterfaceAbstract class

พิจารณาว่าคุณกำลังออกแบบแอพพลิเคชั่นเพื่อแสดงคุณสมบัติทั้งหมดของ Cars ในหลาย ๆ จุดคุณต้องรับมรดกร่วมกันเนื่องจากคุณสมบัติบางอย่างเช่น DigitalFuelMeter, ระบบปรับอากาศ, การปรับที่นั่งเป็นต้นเป็นเรื่องปกติสำหรับรถยนต์ทุกคัน ในทำนองเดียวกันเราต้องการมรดกสำหรับบางคลาสเท่านั้นเนื่องจากคุณสมบัติบางอย่างเช่นระบบเบรก (ABS, EBD) สามารถใช้ได้กับรถยนต์บางคันเท่านั้น

คลาสด้านล่างทำหน้าที่เป็นคลาสพื้นฐานสำหรับรถยนต์ทุกคัน:

public class Cars
{
    public string DigitalFuelMeter()
    {
        return "I have DigitalFuelMeter";
    }

    public string AirCondition()
    {
        return "I have AC";
    }

    public string SeatAdjust()
    {
        return "I can Adjust seat";
    }
}

พิจารณาว่าเรามีชั้นเรียนแยกต่างหากสำหรับรถยนต์แต่ละคัน

public class Alto : Cars
{
    // Have all the features of Car class    
}

public class Verna : Cars
{
    // Have all the features of Car class + Car need to inherit ABS as the Braking technology feature which is not in Cars        
}

public class Cruze : Cars
{
    // Have all the features of Car class + Car need to inherit EBD as the Braking technology feature which is not in Cars        
}

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

public abstract class Brake
{
    public abstract string GetBrakeTechnology();
}

ตอนนี้เรากำลังพยายามสืบทอดจากคลาสนามธรรมนี้และระบบเบรกประเภทนี้ได้ถูกนำมาใช้ใน Verna และ Cruze:

public class Verna : Cars,Brake
{
    public override string GetBrakeTechnology()
    {
        return "I use ABS system for braking";
    }       
}

public class Cruze : Cars,Brake
{
    public override string GetBrakeTechnology()
    {
       return "I use EBD system for braking";
    }         
}

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

interface IBrakeTechnology
{
    string GetBrakeTechnology();
}

และการดำเนินการจะได้รับด้านล่าง:

public class Verna : Cars, IBrakeTechnology
{
    public string GetBrakeTechnology()
    {
        return "I use ABS system for braking";
    }
}

public class Cruze : Cars, IBrakeTechnology
{
   public string GetBrakeTechnology()
   {
       return "I use EBD system for braking";
   }        
}

ตอนนี้ Verna และ Cruze สามารถรับมรดกได้หลายอย่างด้วยเทคโนโลยีเบรกแบบของตัวเองด้วยความช่วยเหลือของ Interface


4
นี่เป็นหนึ่งในคำอธิบายที่ดีที่สุดเพราะเป็นตัวอย่าง
Adam Mendoza

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

9

การเชื่อมต่อเป็นวิธีที่มีน้ำหนักเบาในการบังคับใช้พฤติกรรมบางอย่าง นั่นเป็นวิธีหนึ่งที่จะคิด


8

คำตอบเหล่านี้ยาวเกินไป

  • ส่วนต่อประสานนั้นใช้สำหรับกำหนดพฤติกรรม

  • คลาสนามธรรมมีไว้สำหรับกำหนดสิ่งเองรวมถึงพฤติกรรมของมัน นั่นเป็นเหตุผลที่บางครั้งเราสร้างคลาสนามธรรมด้วยคุณสมบัติพิเศษบางอย่างที่สืบทอดอินเทอร์เฟซ

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


7

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

2) คุณสามารถกำหนดคุณสมบัติในอินเทอร์เฟซดังนั้นคลาสที่ใช้อินเทอร์เฟซนั้นต้องมีคุณสมบัตินั้น

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

  public interface IVariable
  {
      string name {get; set;}
  }

คลาสที่ใช้อินเตอร์เฟสนั้นต้องมีคุณสมบัติเช่นนั้น


7

แม้ว่าคำถามนี้จะค่อนข้างเก่า แต่ฉันต้องการเพิ่มอีกจุดหนึ่งในความโปรดปรานของอินเทอร์เฟซ:

การเชื่อมต่อสามารถฉีดโดยใช้เครื่องมือการพึ่งพาใด ๆ ที่เป็นฉีดระดับนามธรรมสนับสนุนน้อยมาก


1
ฉันเชื่อว่าคุณหมายความว่าเครื่องมือ DI สามารถฉีดคลาสที่ใช้ส่วนต่อประสาน เครื่องมือบางอย่างเช่นนี้ยังสามารถฉีดคลาสที่ได้จากคลาสนามธรรมหรือคุณกำลังบอกว่ามันเป็นไปไม่ได้?
John Saunders

6

จากคำตอบของฉันส่วนใหญ่จัดการกับเมื่อใช้หนึ่งกับอื่น ๆ :

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


6

ประเภทอินเตอร์เฟสกับคลาสพื้นฐานที่เป็นนามธรรม

ที่ดัดแปลงมาจากPro C # 5.0 และ 4.5 .NET กรอบหนังสือ

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

public abstract class CloneableType
{
// Only derived types can support this
// "polymorphic interface." Classes in other
// hierarchies have no access to this abstract
// member.
   public abstract object Clone();
}

รับนิยามนี้เฉพาะสมาชิกที่ขยาย CloneableType เท่านั้นที่สามารถรองรับวิธีการ Clone () หากคุณสร้างชุดคลาสใหม่ที่ไม่ขยายคลาสพื้นฐานนี้คุณจะไม่สามารถรับส่วนต่อประสาน polymorphic นี้ได้ นอกจากนี้คุณอาจจำได้ว่า C # ไม่รองรับการสืบทอดหลายคลาส ดังนั้นหากคุณต้องการสร้าง MiniVan ที่เป็นรถยนต์และ is-a CloneableType คุณจะไม่สามารถทำได้:

// Nope! Multiple inheritance is not possible in C#
// for classes.
public class MiniVan : Car, CloneableType
{
}

อย่างที่คุณคิดว่าประเภทอินเตอร์เฟสมาเพื่อช่วยเหลือ หลังจากที่มีการกำหนดอินเตอร์เฟสมันสามารถใช้งานได้โดยคลาสหรือโครงสร้างใด ๆ ในลำดับชั้นใด ๆ ภายในเนมสเปซหรือแอสเซมบลีใด ๆ (เขียนในภาษาการเขียนโปรแกรม. NET ใด ๆ ) อย่างที่คุณเห็นอินเทอร์เฟซนั้นมีความหลากหลายสูง พิจารณาอินเตอร์เฟส. NET มาตรฐานชื่อ ICloneable ที่กำหนดใน System namespace อินเทอร์เฟซนี้กำหนดวิธีการเดียวชื่อ Clone ():

public interface ICloneable
{
object Clone();
}

6

ตอบคำถามที่สอง: publicตัวแปรที่กำหนดไว้interfaceคือstatic finalโดยค่าเริ่มต้นในขณะที่publicตัวแปรในabstractคลาสเป็นตัวแปรอินสแตนซ์


6

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

หากคุณอ่านพจนานุกรมและแบบอักษรอื่น ๆ คุณอาจพบความหมายต่างกันสำหรับคำเดียวกัน แต่มีคำจำกัดความทั่วไป ฉันคิดว่าทั้งสองความหมายที่ฉันพบในเว็บไซต์นี้ดีมากและเหมาะสมจริงๆ

อินเตอร์เฟซ:

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

นามธรรม:

สิ่งที่มุ่งเน้นในตัวเองคือคุณสมบัติที่สำคัญของสิ่งใดก็ตามที่กว้างขวางกว่าหรือกว้างกว่าหรือมากกว่าในหลาย ๆ อย่าง แก่นแท้.

ตัวอย่าง:

คุณซื้อรถยนต์และต้องการเชื้อเพลิง

ป้อนคำอธิบายรูปภาพที่นี่

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

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

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

ภาคผนวก

นอกจากนี้ฉันคิดว่าคุณควรคำนึงถึงความหมายของคำศัพท์ซึ่งเป็น (จากเว็บไซต์เดียวกันที่กล่าวถึงก่อนหน้านี้):

ประเภท:

จำนวนบุคคลหรือสิ่งต่าง ๆ ที่มองว่าเป็นกลุ่มโดยเหตุผลของคุณลักษณะลักษณะคุณสมบัติหรือลักษณะทั่วไป ชนิด;

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


1
ปุยมากเกินไปอย่าทำให้คนสับสนมากกว่าที่เป็นอยู่แล้ว
ganjeii

5

จากมุมมองการเข้ารหัส

อินเทอร์เฟซสามารถแทนที่คลาสนามธรรมได้ถ้าคลาสนามธรรมมีวิธีนามธรรมเท่านั้น มิฉะนั้นการเปลี่ยนคลาสนามธรรมเป็นอินเทอร์เฟซหมายความว่าคุณจะเสียโอกาสในการใช้งานโค้ดที่ Inheritance จัดเตรียมไว้ให้

จากมุมมองการออกแบบ

เก็บไว้เป็นคลาสนามธรรมหากเป็นความสัมพันธ์ "เป็น" และคุณต้องการชุดย่อยหรือฟังก์ชันทั้งหมด เก็บเป็นอินเทอร์เฟซหากเป็นความสัมพันธ์ "ควรทำ"

ตัดสินใจเลือกสิ่งที่คุณต้องการ: เพียงแค่การบังคับใช้นโยบายหรือการใช้งานโค้ดและนโยบายอีกครั้ง


3

ความแตกต่างอื่น ๆ :

คลาสนามธรรมสามารถมีวิธีการคงที่คุณสมบัติฟิลด์ ฯลฯ และตัวดำเนินการอินเทอร์เฟซไม่สามารถ ตัวดำเนินการ Cast อนุญาตให้ทำการแคสต์ไปยัง / จากคลาสนามธรรม แต่ไม่อนุญาตให้แคสต์ไปยัง / จากอินเทอร์เฟซ

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


ใน Java อินเทอร์เฟซสามารถมีตัวแปรสมาชิก แต่โดยค่าเริ่มต้นพวกเขากลายเป็นสแตติกสาธารณะ .. ดังนั้นอินเทอร์เฟซสามารถมีฟิลด์แบบคงที่
Jitendra Vispute

ใช่อินเตอร์เฟสสามารถมีฟิลด์แบบสแตติก แต่อินเทอร์เฟซไม่สามารถมีวิธีการคงที่
ผู้เรียน
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.