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


118

ฉันรู้ว่านี่เป็นคำถามพื้นฐานมาก แต่ผู้สัมภาษณ์ถามฉันด้วยวิธีที่หลอกลวงมากและฉันก็ทำอะไรไม่ถูก :(

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

ฉันยังไม่เข้าใจสิ่งหนึ่งในอินเทอร์เฟซ เช่นเราใช้

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

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

ผู้สัมภาษณ์กล่าวว่า:

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

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


4
อินเทอร์เฟซเป็นสิ่งที่ฉันพยายามทำความเข้าใจเช่นกัน คำถามที่ดี.
Brian

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

7
SqlConnectionสืบทอดซึ่งการดำเนินการSystem.ComponentModel.Component IDisposable
Lee

2
@MitchWheat - มันไม่ได้หมายถึงตัวอย่างคำถามถามว่าSqlConnectionการดำเนินการIDisposableอย่างไร
ลี

โอ้ลีที่ทำให้ฉันเข้าใจขอบคุณ แต่ฉันยังไม่เห็นว่ามีการกำหนดฟังก์ชันการทำงานของเมธอด "Dispose" อย่างไรหรือที่ใด
ผู้เรียน

คำตอบ:


92

อินเทอร์เฟซนั้นยอดเยี่ยมเมื่อคุณต้องการสร้างสิ่งที่ต้องการ:

using System;

namespace MyInterfaceExample
{
    public interface IMyLogInterface
    {
        //I want to have a specific method that I'll use in MyLogClass
        void WriteLog();       
    }

    public class MyClass : IMyLogInterface
    {

        public void WriteLog()
        {
            Console.Write("MyClass was Logged");
        }
    }

    public class MyOtherClass : IMyLogInterface
    {

        public void WriteLog()
        {
            Console.Write("MyOtherClass was Logged");
            Console.Write("And I Logged it different, than MyClass");
        }
    }

    public class MyLogClass
    {
        //I created a WriteLog method where I can pass as a parameter any object that implements IMyLogInterface.
        public static void WriteLog(IMyLogInterface myLogObject)
        {
            myLogObject.WriteLog(); //So I can use WriteLog here.
        }
    }

    public class MyMainClass
    {
        public void DoSomething()
        {
            MyClass aClass = new MyClass();
            MyOtherClass otherClass = new MyOtherClass();

            MyLogClass.WriteLog(aClass);//MyClass can log, and have his own implementation
            MyLogClass.WriteLog(otherClass); //As MyOtherClass also have his own implementation on how to log.
        }
    }
}

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


3
เฮ้มันดูเหมือนเป็นส่วนผสมที่ดีมากสำหรับฉันที่จะเข้าใจฉันซาบซึ้งจริงๆขอบคุณมาก :) :)
ผู้เรียน

14
คำถามของฉันคือถ้าคุณกำลังสร้างอินสแตนซ์MyClassและMyOtherClassทำไมคุณไม่เรียกaClass.WriteLog()ว่าทำไมเพิ่มขั้นตอนพิเศษนั้น การใช้งานWriteLog()จะยังคงแตกต่างกันไปสำหรับแต่ละคลาส แต่คุณมีอ็อบเจ็กต์อยู่แล้วเหตุใดจึงส่งไปยังคลาสตัวจัดการ
Zach M.

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

2
@ZachM ถ้าฉันพูดถูกคำตอบคือเขาจะไม่สร้างอินสแตนซ์ของคลาส แต่นักพัฒนาคนอื่น ๆ จะสร้างอินสแตนซ์ของคลาสและส่งเป็นพารามิเตอร์ไปยังMyLogClass WriteLogเมธอด ดังนั้นวิธีการของเขาสามารถจัดการกับวัตถุใด ๆ ที่ใช้งานIMyLogInterfaceได้ นี่เป็นอีกหนึ่งโพสต์ที่น่าสนใจ
shaijut

1
คำถามของฉันคือทำไม Interface ??? สถานการณ์ข้างต้นสามารถทำได้โดยคลาสนามธรรมด้วยวิธีนามธรรมทั้งหมด
Abhijit Ojha

52

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

public void DoSomething(Account account) {
  // Do awesome stuff here.
}

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

public void DoSomething(IAccount account) {
  // Do awesome stuff here.
}

โซลูชันนี้ไม่ได้รับการแก้ไขสำหรับการนำไปใช้งานซึ่งหมายความว่าฉันสามารถส่งผ่าน SuperSavingsAccount หรือ ExclusiveAccount ได้ (ทั้งการใช้อินเทอร์เฟซ IAccount) และรับพฤติกรรมที่แตกต่างกันสำหรับแต่ละบัญชีที่ใช้งาน


45

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

ทำไมต้องมีอินเตอร์เฟส

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

ทำไมจึงเป็นนามธรรม


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

1
สำหรับตัวอย่างที่ใช้ได้จริงเกี่ยวกับอินเทอร์เฟซและ SOA เราแชร์ WCF Interfaces ( DataContracts) ของเราใน. NET Assembly ( เช่น Contracts.Shared.dll ) เพื่อให้ผู้บริโภคไคลเอ็นต์. NET สามารถทำงานร่วมกันChannelFactoryได้อย่างง่ายดายโดยใช้ ( หลีกเลี่ยงการสร้างรหัสผ่าน Add Service Reference เป็นต้น ) หรือใช้Add Service Reference with Shared types
SliverNinja - MSFT

ถ้าฉันจะประกาศเฉพาะวิธีนามธรรมภายในคาลสนามธรรมคลาสนามธรรมจะทำหน้าที่เป็นอินเทอร์เฟซแล้วทำไมเราถึงต้องการอินเทอร์เฟซ?
Abhijit Ojha

25

ใส่คำอธิบายภาพที่นี่

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

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


สิ่งนี้สมเหตุสมผล แต่ฉันยังคงดิ้นรนเพื่อทำความเข้าใจคุณเพียงแค่ไม่สร้างคลาสพื้นฐานสำหรับ PowerSocket และสิ่งอื่น ๆ ทั้งหมดจะสืบทอดมาหากจำเป็น ในทางเทคนิค Power Sockets ไม่มีความคิดเกี่ยวกับคลาสอื่น ๆ
altaaf.hussein

ฉันคิดว่าเนื่องจากไม่อนุญาตให้มีการสืบทอดหลายรายการใน C #
Hugh Seagraves

22

ในคำเดียว - เพราะPolymorphism !

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

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

4

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


3
คุณสามารถหาประเภทเป็ดใน. net4 ด้วยประเภทไดนามิก
Tony Hopkinson

4

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

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

ตอนนี้ขอขุดในลิงค์ที่ฉันให้ไปแล้ว

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

public class clsBike:IChoice
{
   #region IChoice Members
    public string Buy()
    {
       return ("You choose Bike");
    }
    #endregion
}

และ

public class clsCar:IChoice
{
   #region IChoice Members
    public string Buy()
    {
       return ("You choose Car");
    }
    #endregion
}

และทั้งสองมีสัญญา IChoice ที่พูดง่ายๆว่าชั้นเรียนของฉันควรมีวิธีการซื้อ

public interface IChoice
{
    string Buy();
}

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

public abstract class Choice
{
    public abstract string Discount { get; }
    public abstract string Type { get; }
    public string Buy()
    {
       return "You buy" + Type + " with " + Discount;
}
public class clsBike: Choice
{
    public abstract string Discount { get { return "10% Discount Off"; } }
    public abstract string Type { get { return "Bike"; } }
}

public class clsCar:Choice
{
    public abstract string Discount { get { return " $15K Less"; } }
    public abstract string Type { get { return "Car"; } }
}

ตอนนี้ใช้คลาสโรงงานคุณสามารถบรรลุสิ่งเดียวกัน แต่ในการใช้บทคัดย่อคุณปล่อยให้คลาสพื้นฐานดำเนินการตามBuy()วิธีการ

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


2

ด้วยอินเทอร์เฟซคุณสามารถทำสิ่งต่อไปนี้:

1) สร้างอินเทอร์เฟซที่แยกออกจากกันซึ่งมีการตัดการใช้งานที่แตกต่างกันออกไปทำให้ได้อินเทอร์เฟซที่เหนียวแน่นมากขึ้น

2) อนุญาตให้ใช้หลายวิธีที่มีชื่อเดียวกันระหว่างอินเทอร์เฟซเพราะเดี๋ยวก่อนคุณไม่มีการใช้งานที่ขัดแย้งกันเพียงแค่ลายเซ็น

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

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

มีเหตุผลอื่น ๆ อีกมากมายที่ฉันแน่ใจนี่เป็นเพียงบางส่วน

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


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

2

เป็นตัวอย่างจริงของ @ user2211290 คำตอบ:

ทั้งสองArrayและมีอินเตอร์เฟซList IListด้านล่างเรามี a string[]และ a List<string>และตรวจสอบทั้งสองด้วยวิธีการเดียวโดยใช้IList :

string[] col1 = { "zero", "one", "two", "three", "four"};
List<string> col2 = new List<string>{ "zero", "one", "two", "three"};

//a methode that manipulates both of our collections with IList
static void CheckForDigit(IList collection, string digit)
{
    Console.Write(collection.Contains(digit));
    Console.Write("----");
    Console.WriteLine(collection.ToString()); //writes the type of collection
}

static void Main()
{
    CheckForDigit(col1, "one");   //True----System.String[]
    CheckForDigit(col2, "one");   //True----System.Collections.Generic.List`1[System.String]



//Another test:

    CheckForDigit(col1, "four");   //True----System.String[]
    CheckForDigit(col2, "four");   //false----System.Collections.Generic.List`1[System.String]
}

1

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

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


1

ทั้งคลาสนามธรรมและอินเทอร์เฟซเป็นสัญญา

แนวคิดของสัญญาคือคุณระบุพฤติกรรมบางอย่าง หากคุณบอกว่าคุณได้ดำเนินการแสดงว่าคุณได้ตกลงทำสัญญาแล้ว

การเลือกนามธรรมมากกว่าอินเตอร์เฟซคือ

ผู้สืบทอดที่ไม่ใช่นามธรรมของคลาสนามธรรมจะดำเนินการตามสัญญา

กับ

คลาสใด ๆ ที่ใช้อินเทอร์เฟซจะดำเนินการตามสัญญา

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


1

การเชื่อมต่อคือการสร้างนามธรรม (แม่แบบ) ของสิ่งที่เป็นนามธรรม (คลาส) ของความเป็นจริง (วัตถุ)

อินเทอร์เฟซคือการระบุเงื่อนไขสัญญาโดยไม่ต้องมีการใช้งานโดยคลาส

อินเทอร์เฟซเป็นข้อมูลจำเพาะ:

  • อินเทอร์เฟซเป็นสิ่งประดิษฐ์เวลาออกแบบเพื่อระบุพฤติกรรมที่ไม่สามารถเคลื่อนที่ได้ของแนวคิดเนื่องจากเป็นแบบเดี่ยวและแบบคงที่

  • คลาสเป็นสิ่งประดิษฐ์เวลาใช้งานเพื่อระบุโครงสร้างเคลื่อนที่ของความเป็นจริงในขณะที่มันโต้ตอบและเคลื่อนย้าย

อินเทอร์เฟซคืออะไร?

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

คุณเพิ่งกำหนดอินเทอร์เฟซที่มีคุณสมบัติและการดำเนินการ ด้วยเหตุนี้คุณจึงไม่ได้กำหนด modus operandi แต่มีเพียงคุณลักษณะและความสามารถโดยไม่รู้ว่าสิ่งต่างๆทำงานอย่างไรคุณได้กำหนดความสามารถและความแตกต่าง

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

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

เพื่อให้เข้าใจว่าเราสามารถอ้างถึงการเข้ารหัส Pascal Object ที่คุณกำหนดอินเทอร์เฟซและส่วนการนำไปใช้งานในหน่วย ในอินเทอร์เฟซคุณกำหนดประเภทและในการใช้งานคุณใช้ประเภท:

unit UnitName;

interface

type
  TheClass = class
  public
    procedure TheMethod;
  end;

implementation

class procedure TheClass.TheMethod;
begin
end;

ที่นี่ส่วนอินเทอร์เฟซตรงกับการออกแบบคลาส UML ในขณะที่ประเภทอินเตอร์เฟสจึงเป็นสิ่งอื่น ๆ

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

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

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

คลาสคืออะไร?

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

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

ดังนั้นคลาสนามธรรมจึงเทียบเท่ากับอินเตอร์เฟสจากมุมมองของคอมไพเลอร์

ข้อมูลมากกว่านี้

โปรโตคอล (การเขียนโปรแกรมเชิงวัตถุ)

C # - อินเทอร์เฟซ

C # - ชั้นเรียน


1

ให้ฉันบอกคุณเกี่ยวกับเครื่องปิ้งขนมปังที่บินได้

เครื่องปิ้งขนมปัง

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

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

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

การออกแบบที่ไม่สำคัญเหล่านี้เกี่ยวข้องกับการสืบทอดหลาย ๆ แบบซึ่งในรูปแบบ "จริง" คือเมื่อคลาสที่สืบทอดไม่ใช่จากคลาสพื้นฐานเพียงคลาสเดียว แต่มาจากคลาสพื้นฐานสองคลาสขึ้นไป รูปแบบที่แท้จริงนี้ไม่สามารถทำได้ใน C # แต่ก่อนที่ภาษาเช่น C # และ Java จะมีขึ้นมาภาษาที่ปกครองคือ C ++ ซึ่งรองรับการสืบทอดหลายรายการที่แท้จริง น่าเสียดายที่การสืบทอดหลายรายการที่แท้จริงนั้นไม่ใช่ความคิดที่ดีนักเพราะมันทำให้การออกแบบภาษาซับซ้อนขึ้นอย่างมากและยังก่อให้เกิดปัญหาต่างๆเช่น "Diamond Problem" ที่มีชื่อเสียง (โปรดดู"เป็นปัญหาที่แน่นอนกับมรดกหลายอะไร?" คำตอบโดย J ฟรานซิส )

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

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

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

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


0

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


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

0

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

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

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

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


-2

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

เช่นถ้าฉันมีสองเอนทิตีพูดว่า Animal and Human ฉันจะไปที่ Interface ซึ่งถ้าฉันต้องไปพูดรายละเอียดว่า Tiger, lion และต้องการเกี่ยวข้องกับ Animal จากนั้นจะเลือกคลาส Animal Abstract ..

จะมีลักษณะดังนี้

   Interface             
   ____|____
  |        |
Animal   Human



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