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