มีความแตกต่างระหว่างอินเตอร์เฟสและคลาส abstract ที่มีเมธอด abstract เท่านั้นหรือไม่?


9

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

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


ภาษาไหน?
วินไคลน์

เท่าที่ผมสามารถบอกได้คำถามของคุณจะได้รับคำตอบในที่ซ้ำกันสองครั้ง : ที่นี่และที่นี่ และสองคำตอบนี้เป็นผู้ไม่เชื่อเรื่องภาษาไม่มีอะไรพิเศษสำหรับ C # นั่น
ริ้น

3
@ ว่างฉันไม่เห็นด้วยกับสถานะซ้ำที่ใช้กับคำถามของคุณดังนั้นฉันจึงเปิดใหม่ เพิ่มเติมฉันแก้ไขคำถามของคุณเพื่อชี้แจงสิ่งที่ฉันเชื่อว่าคุณถาม
maple_shaft

คำตอบ:


22

ในทางเทคนิคแล้วความแตกต่างนั้นไม่สำคัญมากนัก แต่ในทางแนวคิดแล้วมันมีความแตกต่างอย่างสิ้นเชิงและนำไปสู่ความแตกต่างทางเทคนิคที่คนอื่นพูดถึง

Superclass นามธรรมเป็นสิ่งที่ดูเหมือนว่ามันเป็นประเภททั่วไปที่มีการใช้ร่วมกันโดยประเภทอื่น ๆ เช่น Cats and Dogs เป็นสัตว์

อินเทอร์เฟซเป็นสิ่งที่ดูเหมือนกับเป็นอินเทอร์เฟซที่คลาสอื่นสามารถสื่อสารกับวัตถุได้ หากคุณต้องการสร้าง Cat Walk คุณก็โอเคทำให้ Cat ใช้อินเทอร์เฟซ CanWalk เหมือนกันสำหรับจิ้งจกแม้ว่าพวกเขาจะเดินแตกต่างกันมาก ในทางกลับกันงูไม่ได้ใช้ CanWalk ดังนั้นคุณจึงไม่สามารถบอกให้ Walk ในขณะเดียวกัน Lizard and Snake (หรืออาจจะเป็น subclasses ที่ชัดเจนกว่า - ฉันไม่ใช่ผู้เชี่ยวชาญ) อาจทำให้ผิวของพวกมันหลั่งและใช้ CanShed ในขณะที่แมวไม่สามารถทำเช่นนั้นได้

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

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

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


4
+1 แม้ว่าแมวจะทำให้แมวดูน่ารำคาญกว่างูหรือกิ้งก่า
Matthew Flynn

ในทางเทคนิค: วิธีบทคัดย่อสามารถป้องกันได้ วิธีการเชื่อมต่อไม่สามารถ
Jacques Koorts

19

ในภาษา OOP ส่วนใหญ่คลาสที่ใช้งานสามารถสืบทอดมาจากคลาสนามธรรมเพียงคลาสเดียว แต่ใช้หลายอินเตอร์เฟส


3
มากที่สุด? อันไหนที่คุณนับ ภาษา OOP ส่วนใหญ่ที่ฉันรู้จักไม่มีส่วนต่อประสานหรือคลาสนามธรรม C ++ มีคลาสนามธรรมเท่านั้น
kevin cline

10
@kevincline: อาจเป็น C #, Java และ VB.NET
tdammers

1
@ kevincline ฉันคิดว่ามีเพียง "มีทั้งคู่" ที่ขาดไป IIRC ใน Ada แรงจูงใจสำหรับอินเทอร์เฟซคืออันหนึ่งนักออกแบบไม่ต้องการคุณสมบัติการสืบทอดหลายแบบทั่วไป แต่กรณีพิเศษของอินเทอร์เฟซนั้นถือว่าสำคัญเกินไปที่จะไม่ให้
AProgrammer

@tdammers: LOL นั่นเป็นเรื่องตลกใช่มั้ย?
วินไคลน์

3

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

ในภาษาอย่าง PHP และ C # อินเทอร์เฟซมีวิธีการที่ทำให้เกิด polymorphism ที่คล้ายคลึงกันแม้ว่าฉันจะไม่ชอบเรียกมันว่า "การสืบทอด" เนื่องจากมีความแตกต่างทางแนวคิดระหว่างการสืบทอดคลาสนามธรรมและการใช้อินเตอร์เฟส อินเทอร์เฟซลบปัญหาความขัดแย้งเพราะพวกเขาเองไม่ได้นำไปใช้

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

ความแตกต่างทางความคิดที่สำคัญคือว่าเมื่อชั้นเรียนสืบทอดชั้นอื่น (นามธรรมหรือไม่) มีความสัมพันธ์ของ "คือ" เพื่อให้Carเป็นVehicleและเป็นDog Animalด้วยอินเตอร์เฟสมันเป็นสิ่งที่วัตถุทำ ดังนั้นทั้งสองCarและDogสามารถMove()และผู้บริโภครู้ว่ามันเป็นเพราะพวกเขาใช้Movableแต่รถไม่แน่นอนหรือDog Animalและการนำไปปฏิบัติจะแตกต่างกัน (ล้อกับขา) แต่รหัสการบริโภคไม่ควรและไม่ควรสนใจ อินเทอร์เฟซทั้งหมดเกี่ยวกับรหัสการบริโภคมากกว่าการนำไปใช้

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


อินเตอร์เฟซที่เป็นชนิดเป็นอย่างดีเพื่อให้คุณสามารถมี IAnimal ซึ่งทั้งสองDogและมีCat
Amy Blankenship

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

2

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

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


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

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

เพียงแค่ทราบ ในบางภาษาวิธีเสมือนส่วนตัวสามารถถูกแทนที่ในคลาสที่ได้รับ
Johan Boulé

2

ใช่มันแตกต่างกัน ไม่เช่นนั้นนักออกแบบภาษาจะไม่ได้ให้ทั้งสองอย่าง ฉันรู้สองภาษาที่แยกคลาสและอินเตอร์เฟส: Java และ C #, โคลนนิ่งกลายพันธุ์ของ Java ผู้ออกแบบสร้างอินเตอร์เฟสเพื่อหลีกเลี่ยงการสนับสนุนการสืบทอดคลาสหลายคลาส ภาษาอื่นส่วนใหญ่รองรับการสืบทอดหลายคลาสดังนั้นจึงไม่แยกคลาสและอินเทอร์เฟซ


2

ฉันคิดว่าความแตกต่างที่สำคัญคือ: ในคลาสนามธรรม - แม้ว่าวิธีทั้งหมดเป็นนามธรรมทั้งหมดพวกเขายังสามารถให้ข้อมูลสมาชิก (ตัวแปรอินสแตนซ์) และรหัสบางส่วนให้กับคลาสที่ใช้มัน (ในรูปแบบของวิธีการส่วนตัวหรือคอนสตรัคเตอร์) บล็อกแบบคงที่; ทำส่วนหนึ่งของงานสำหรับคลาสย่อยและช่วยเหลือพวกเขาในการนำไปปฏิบัติ

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

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


1
ไม่ได้กำหนดวิธีที่เป็นนามธรรมโดยไม่มีการใช้งานและปล่อยให้การนำไปใช้กับคลาสที่รับค่าหรือไม่
Ivan Pintar

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

@Pinetree ในทางปฏิบัติส่วนใหญ่คุณจะต้องการรหัส "ของจริง" อย่างน้อยในคลาสนามธรรมของคุณ (อย่างน้อยก็ในภาษาที่ฉันใช้ซึ่งไม่มีโครงสร้างพิเศษสำหรับคลาสนามธรรม)
Amy Blankenship

@AmyBlankenship ใช่ส่วนใหญ่เวลานามธรรมจะมีรหัส "ของจริง" (นั่นคือสิ่งที่พวกเขามีสำหรับ) แต่ฉันหมายถึงวิธีนามธรรมภายในบริบทของคลาสนามธรรมล้วนๆซึ่งทำหน้าที่เป็นส่วนต่อประสานในภาษาอย่าง C ++ ซึ่งไม่มีส่วนต่อประสาน
Ivan Pintar
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.