ทำไมคุณต้องใช้อินเทอร์เฟซหากมีคลาสนามธรรมอยู่แล้ว?
เพื่อป้องกันการสืบทอดหลายรายการ (อาจทำให้เกิดปัญหาที่ทราบหลายประการ)
หนึ่งในปัญหาดังกล่าว:
"ปัญหาเพชร" (บางครั้งเรียกว่า "เพชรแห่งความตาย") คือความกำกวมที่เกิดขึ้นเมื่อสองคลาส 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
) ในการเรียก / ใช้
คลาสที่ใช้อินเตอร์เฟสต้องใช้เมธอดทั้งหมดซึ่งอินเตอร์เฟสทำ / มี
ฉันหวังว่าฉันจะไม่ทำซ้ำตัวเองมากเกินไป