จุดเชื่อมต่อใน PHP คืออะไร?


224

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

คลาสนามธรรมช่วยให้คุณทำสิ่งเดียวกันพร้อมกับเพิ่มรหัสไปยังวิธีการ

ตอนนี้ถ้าคุณสามารถบรรลุเป้าหมายเดียวกันกับคลาสนามธรรมทำไมเราถึงต้องมีแนวคิดของอินเทอร์เฟซ?

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


4
คุณต้องอ่านสิ่งนี้: stackoverflow.com/a/384067/14673
Luc M

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

คำตอบ:


142

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

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


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

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

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

123

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


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

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

70

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

หนึ่งในปัญหาดังกล่าว:

"ปัญหาเพชร" (บางครั้งเรียกว่า "เพชรแห่งความตาย") คือความกำกวมที่เกิดขึ้นเมื่อสองคลาส B และ C สืบทอดมาจาก A และคลาส D สืบทอดจากทั้ง B และ C หากมีวิธีใน A ที่ B และ C มีการแทนที่และ D ไม่ได้แทนที่มันแล้วรุ่นของวิธีการที่ D สืบทอดมา: ที่ของ B หรือที่ของ C?

ที่มา: https://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem

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

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

// Methods inside this interface must be implemented in all classes which implement this interface.
interface IPersonService
{   
    public function Create($personObject);
}

class MySqlPerson implements IPersonService
{
    public function Create($personObject)
    {
        // Create a new person in MySql database.
    }
}

class MongoPerson implements IPersonService
{
    public function Create($personObject)
    {
        // Mongo database creates a new person differently then MySQL does. But the code outside of this method doesn't care how a person will be added to the database, all it has to know is that the method Create() has 1 parameter (the person object).
    }
}

วิธีนี้Create()จะใช้วิธีการแบบเดียวกันเสมอ ไม่สำคัญว่าเราจะใช้MySqlPersonคลาสหรือMongoPersonคลาส วิธีที่เราใช้วิธียังคงเหมือนเดิม (อินเทอร์เฟซยังคงเหมือนเดิม)

ตัวอย่างเช่นมันจะถูกใช้เช่นนี้ (ทุกที่ในรหัสของเรา):

new MySqlPerson()->Create($personObject);
new MongoPerson()->Create($personObject);

ด้วยวิธีนี้สิ่งนี้ไม่สามารถเกิดขึ้นได้:

new MySqlPerson()->Create($personObject)
new MongoPerson()->Create($personsName, $personsAge);

การจดจำอินเทอร์เฟซเดียวนั้นง่ายกว่ามากและใช้อินเทอร์เฟซเดียวกันทุกหนทุกแห่งมากกว่าหลาย ๆ

วิธีนี้วิธีการด้านในCreate()อาจแตกต่างกันสำหรับคลาสที่แตกต่างกันโดยไม่มีผลต่อรหัส "นอก" ซึ่งเรียกวิธีการนี้ โค้ดภายนอกทั้งหมดต้องรู้ว่าเมธอดCreate()นั้นมี 1 พารามิเตอร์ ( $personObject) เพราะนั่นคือวิธีที่โค้ดภายนอกจะใช้ / เรียกใช้เมธอด โค้ดภายนอกไม่สนใจสิ่งที่เกิดขึ้นในวิธีการนั้น มีเพียงรู้วิธีใช้ / เรียกใช้

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

คลาสที่ใช้อินเตอร์เฟสต้องใช้เมธอดทั้งหมดซึ่งอินเตอร์เฟสทำ / มี

ฉันหวังว่าฉันจะไม่ทำซ้ำตัวเองมากเกินไป


การเปรียบเทียบที่ดีมากกับคันเหยียบ!
James

24

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

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

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

ในทางตรงกันข้ามฉันยังสามารถสร้างวัตถุที่ไม่ได้ขยายจากบัญชีพูดคลาสนามธรรมของผู้ใช้และยังคงใช้ฟังก์ชั่น Listable และ Editable แต่ไม่สามารถแก้ไขได้ Versionable ซึ่งไม่สมเหตุสมผล

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

การเพิ่ม APIs เหล่านี้ทั้งหมดสำหรับ Editable, Listable และ Versionable ลงในคลาส abstract นั้นไม่เพียง แต่จะมีความยุ่งเหยิงและน่าเกลียดเท่านั้น แต่จะทำซ้ำอินเตอร์เฟสทั่วไปในบัญชีและผู้ใช้หรือบังคับให้วัตถุผู้ใช้ของฉัน ข้อยกเว้น


นี่มันอยู่ตรงนี้ บังคับใช้ devs อย่างเข้มงวดเพื่อใช้วิธีการของคุณโดยไม่ต้องขยายหรือเขียนทับพวกเขา
Nick

21

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

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

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

ฉันคิดว่าอินเทอร์เฟซเป็นรูปแบบสำหรับนักพัฒนาภายนอกหรือชุดกฎเสริมเพื่อให้แน่ใจว่าสิ่งต่าง ๆ นั้นถูกต้องเสมอ


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

13

คุณจะใช้ส่วนต่อประสานใน PHP:

  1. ในการซ่อนการนำไปใช้งาน - สร้างโปรโตคอลการเข้าถึงไปยังคลาสของออบเจ็กต์การเปลี่ยนแปลงการนำไปใช้งานพื้นฐานโดยไม่ต้องทำการปรับสภาพใหม่ในสถานที่ทั้งหมดที่คุณใช้วัตถุนั้น
  2. เพื่อตรวจสอบประเภท - ในการตรวจสอบให้แน่ใจว่าพารามิเตอร์มีประเภทเฉพาะ $object instanceof MyInterface
  3. เพื่อบังคับใช้การตรวจสอบพารามิเตอร์ที่รันไทม์
  4. เมื่อต้องการใช้หลายพฤติกรรมในคลาสเดียว (สร้างชนิดที่ซับซ้อน)

    คลาสของรถใช้ EngineInterface, BodyInterface, SteeringInterface {

เพื่อให้Carวัตถุ ca ตอนนี้start(), stop()(EngineInterface) หรือgoRight(), goLeft()(อินเตอร์เฟซที่พวงมาลัย)

และสิ่งอื่น ๆ ที่ฉันนึกไม่ออกตอนนี้

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

จากการคิดใน Java:

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


10

อินเทอร์เฟซไม่ได้เป็นฐานที่คลาสสามารถขยายได้ แต่เป็นแผนที่ของฟังก์ชันที่ต้องการ

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

<?php

interface ImportableFeed 
{
    public function getEvents();
}

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

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

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

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

<?php
interface ImportableFeed 
{
    /**
     * @return array
     */
    public function getEvents();
}

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


คำอธิบายที่ดี :) ขอบคุณ!
Razvan.432

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

8

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

interface Readable {
  String read();
}

List<Readable> readables; // dunno what these actually are, but we know they have read();
for(Readable reader : readables)
  System.out.println(reader.read());

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

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


6

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

มันเป็นความจริงที่อินเตอร์เฟสนั้นมีประโยชน์น้อยกว่า / มีความหมายมากกว่าเมื่อเปรียบเทียบกับ Java ในทางกลับกัน PHP6 จะแนะนำคำใบ้ประเภทมากยิ่งขึ้นรวมถึงคำใบ้ประเภทสำหรับค่าตอบแทน สิ่งนี้ควรเพิ่มค่าบางอย่างในอินเทอร์เฟซ PHP

tl; dr: อินเตอร์เฟสกำหนดรายการของวิธีการที่ต้องปฏิบัติตาม (คิดว่า API) ในขณะที่คลาสนามธรรมให้ฟังก์ชันพื้นฐาน / ทั่วไปซึ่งคลาสย่อยปรับแต่งตามความต้องการเฉพาะ


PHP 6 จะไม่ถูกปล่อยออกมา PHP 6 เป็นโครงการที่อยู่ระหว่างการพัฒนาตั้งแต่ปี 2548-2553 แต่ล่าช้าและยกเลิกไปในที่สุด PHP 7 เป็นเวอร์ชันถัดไปส่วนใหญ่เพื่อหลีกเลี่ยงความสับสนกับโครงการ PHP 6 ในอดีต
Ashu Jha

5

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

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

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


4

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

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

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

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


2

ด้านล่างนี้เป็นจุดสำหรับ PHP Interface

  1. มันถูกใช้เพื่อกำหนดไม่จำเป็นต้องมีวิธีการในชั้นเรียน [ถ้าคุณต้องการที่จะโหลด html แล้ว id และชื่อที่จำเป็นดังนั้นในกรณีนี้อินเทอร์เฟซกรณีรวม setID และ setName]
  2. ส่วนต่อประสานกำลังบังคับคลาสให้รวมวิธีการทั้งหมดที่กำหนดไว้
  3. คุณสามารถกำหนดวิธีการในส่วนต่อประสานกับการเข้าถึงสาธารณะ
  4. คุณยังสามารถขยายส่วนต่อประสานเช่นคลาส คุณสามารถขยายส่วนต่อประสานใน php โดยใช้คำหลักที่ขยาย
  5. ขยายหลายอินเตอร์เฟส
  6. คุณไม่สามารถใช้ 2 อินเตอร์เฟสได้หากทั้งสองฟังก์ชั่นใช้ชื่อเดียวกัน มันจะผิดพลาด

รหัสตัวอย่าง:

interface test{
    public function A($i);
    public function B($j = 20);
}

class xyz implements test{
    public function A($a){
        echo "CLASS A Value is ".$a;
    }
    public function B($b){
        echo "CLASS B Value is ".$b;
    }
}
$x = new xyz();
echo $x->A(11);
echo "<br/>";
echo $x->B(10);

2

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

1. อินเทอร์เฟซสามารถรวมวิธีนามธรรมและค่าคงที่ แต่ไม่สามารถมีวิธีและตัวแปรที่เป็นรูปธรรม

2. วิธีการทั้งหมดในส่วนต่อประสานจะต้องอยู่ในขอบเขตการมองเห็นสาธารณะ

3.A class สามารถใช้มากกว่าหนึ่งอินเตอร์เฟสในขณะที่มันสามารถสืบทอดจากคลาสนามธรรมเพียงคลาสเดียวเท่านั้น

                                  interface                      abstract class
the code                     - abstract methods               - abstract methods
                             - constants                      - constants                  
                                                              - concrete methods
                                                              - concrete variables

access modifiers             
                             - public                         - public
                                                              - protected
                                                              - private
                                                                etc.
number of parents          The same class can implement
                           more than 1 interface              The child class can 
                                                              inherit only from 1 abstract class

หวังว่าสิ่งนี้จะช่วยให้ทุกคนเข้าใจ!


2

การเชื่อมต่อเป็นเหมือนยีนส์ของคุณ

คลาสนามธรรมเป็นเหมือนพ่อแม่ที่แท้จริงของคุณ

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


2

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

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

กฎ

  1. อินเทอร์เฟซไม่สามารถยกตัวอย่างได้

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

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

  4. อินเทอร์เฟซต้องไม่ประกาศตัวสร้างหรือ destructors เนื่องจากเป็นรายละเอียดการใช้งานในระดับชั้น

  5. วิธีการทั้งหมดในส่วนต่อประสานต้องมีการเปิดเผยต่อสาธารณะ

ตอนนี้ลองมาเป็นตัวอย่าง สมมติว่าเรามีของเล่นสองชิ้น: อันหนึ่งคือสุนัขและอีกอันคือแมว

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

เมื่อผู้ใช้กดปุ่มพูดของเล่นต้องพูดมันไม่สำคัญว่าจะเป็นสุนัขหรือแมว

นี่เป็นกรณีที่ดีในการใช้อินเทอร์เฟซไม่ใช่คลาสนามธรรมเนื่องจากการใช้งานที่แตกต่างกัน ทำไม? จำ

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

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