C #: คลาสนามธรรมจำเป็นต้องใช้อินเทอร์เฟซหรือไม่?


131

รหัสทดสอบของฉันใน C #:

namespace DSnA
{
    public abstract class Test : IComparable
    {

    }
}

ผลลัพธ์ในข้อผิดพลาดของคอมไพเลอร์ต่อไปนี้:

error CS0535: 'DSnA.Test' does not implement interface member
'System.IComparable.CompareTo(object)'

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


ฮ่าฮ่า ฉันเขียนสิ่งหนึ่งแล้วตัดสินใจที่จะเปลี่ยนแปลง ขอโทษ :)
Joel

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

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

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

คำตอบ:


141

ใน C # คลาสที่ใช้อินเทอร์เฟซจะต้องกำหนดสมาชิกทั้งหมดของอินเทอร์เฟซนั้น ในกรณีของคลาสนามธรรมคุณเพียงแค่กำหนดสมาชิกเหล่านั้นด้วยabstractคีย์เวิร์ด:

interface IFoo
{
    void Bar();
}

abstract class Foo : IFoo
{
    public abstract void Bar();
}

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

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


2
@ เบ็นเพิ่งเห็นความคิดเห็นของคุณ คุณอาจคิดออกแล้ว แต่ในกรณีที่มีคนต้องการ ตรวจสอบการใช้อินเทอร์เฟซที่ชัดเจน: msdn.microsoft.com/en-us/library/ms173157.aspx
Joel

2
@Joel @Ben ฉันไม่คิดว่าอินเทอร์เฟซที่ชัดเจนสามารถทำงานกับคลาสนามธรรมได้ ในโค้ดตัวอย่างด้านบนให้เปลี่ยนคำจำกัดความFooเป็นpublic abstract void IFoo.Bar();และคุณได้รับการร้องเรียนว่า "สาธารณะ" และ "นามธรรม" ไม่ใช่ตัวแก้ไขที่ถูกต้อง
Darren Cook

8
สิ่งนี้ไม่ได้ตอบคำถามว่าทำไมสิ่งนี้ถึงจำเป็นเลยโดยที่นี่เป็นคลาสนามธรรมและคอมไพเลอร์ควรรู้วิธีเติมคำในช่องว่าง ใน Java สิ่งนี้ไม่จำเป็นซึ่งอนุญาตให้มีรูปแบบที่มีประโยชน์หลายอย่างเช่นรูปแบบมัณฑนากรบนคอนเทนเนอร์ ioc เช่น Spring / JavaEE (เมื่อคุณต้องการตกแต่งวิธีการเฉพาะของอินเทอร์เฟซที่มีการจัดการ) การใช้งาน in.net แบบเดียวกันจะต้องบังคับให้นักพัฒนามีความละเอียดมากโดยเฉพาะในอินเทอร์เฟซขนาดใหญ่เช่น ISession ของ nhibernate
Sheepy

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

1
@ Sheepy - จริง แต่ IMHO คุณเข้าใจผิดว่าผู้ถามต้องการอะไรและนี่คือ "คำตอบ" อย่างไร ฉันก็มีคำถามเหมือนกัน - เพราะมันไม่สมเหตุสมผลที่จะต้องจัดหาการนำไปใช้งานดังนั้นฉันจึงติดขัด คำตอบคือคุณไม่จำเป็นต้อง " ใช้งาน " แต่นี่คือสิ่งที่คุณต้องทำเพื่อบอกคอมไพเลอร์ว่าคุณจะไม่นำไปใช้ (คำถามที่คุณ [ถูกต้อง] บอกว่านี่ไม่ใช่คำตอบคงไม่ใช่คำถาม stackoverflow ที่เหมาะสม - มันคงจะถูกปิดโดยไม่ตั้งใจ)
ToolmakerSteve

10

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

https://msdn.microsoft.com/en-us/library/Aa664595(v=VS.71).aspx


1
คำตอบที่ชัดเจนและยอดเยี่ยมที่คุณระบุทั้งสองสถานการณ์เนื่องจากบางครั้งคุณอาจต้องการใช้พฤติกรรมในคลาสพื้นฐาน
VinKel

คำถามหนึ่งที่เกิดขึ้นที่นี่คือทำไมการประกาศ C # แบบสำเร็จรูปเหล่านี้ (ซึ่งเห็นได้ชัดว่าเป็น) จำเป็นต้องมีอยู่ในคลาสนามธรรมซึ่งอาจกระชับและสั้นลง (จึงทำให้ชั้นเรียนสับสน) ในโครงการ C # ของฉันฉันมีคลาสและอินเทอร์เฟซที่เป็นนามธรรมมากมายและสิ่งที่ฉันทำเกือบตลอดเวลาคือการคัดลอกและวางการประกาศวิธีการใน Visual Studio
forsberg

5

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

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