ฉันค้นพบอินเทอร์เฟซและฉันเริ่มรักพวกเขา ความสวยงามของอินเทอร์เฟซคือมันเป็นสัญญาและวัตถุใด ๆ ที่ตอบสนองสัญญานั้นสามารถใช้ได้ทุกที่ที่ต้องการอินเตอร์เฟส
ปัญหาของอินเทอร์เฟซคือมันไม่สามารถมีการใช้งานเริ่มต้นซึ่งเป็นคุณสมบัติที่เจ็บปวดสำหรับคุณสมบัติทางโลกและกำจัด DRY สิ่งนี้ก็เป็นสิ่งที่ดีเพราะมันทำให้การใช้งานและระบบแยกจากกัน ในทางกลับกันมรดกยังคงรักษาคัปปลิ้งที่แน่นกว่าและมีศักยภาพที่จะทำลายการห่อหุ้ม
กรณีที่ 1 (การสืบทอดกับสมาชิกส่วนตัวการห่อหุ้มที่ดีเข้าด้วยกันอย่างแน่นหนา)
class Employee
{
int money_earned;
string name;
public:
void do_work(){money_earned++;};
string get_name(return name;);
};
class Nurse : public Employee:
{
public:
void do_work(/*do work. Oops, can't update money_earned. Unaware I have to call superclass' do_work()*/);
};
void HireNurse(Nurse *n)
{
nurse->do_work();
)
กรณีที่ 2 (เพียงอินเทอร์เฟซ)
class IEmployee
{
virtual void do_work()=0;
virtual string get_name()=0;
};
//class Nurse implements IEmployee.
//But now, for each employee, must repeat the get_name() implementation,
//and add a name member string, which breaks DRY.
กรณีที่ 3: (ดีที่สุดของทั้งสองโลก)
คล้ายกับกรณีที่ 1 แต่คิดว่า (สมมุติฐาน) C ++ไม่อนุญาตให้เอาชนะวิธีการยกเว้นวิธีการเหล่านั้นที่มีความบริสุทธิ์เสมือน
ดังนั้นในกรณีที่ 1 การแทนที่ do_work () จะทำให้เกิดข้อผิดพลาดในเวลาคอมไพล์ ในการแก้ไขปัญหานี้เราได้ตั้ง do_work () เป็นเสมือนจริงและเพิ่มเมธอด increment_money_earned () แยกต่างหาก ตัวอย่างเช่น:
class Employee
{
int money_earned;
string name;
public:
virtual void do_work()=0;
void increment_money_earned(money_earned++;);
string get_name(return name;);
};
class Nurse : public Employee:
{
public:
void do_work(/*do work*/ increment_money_earned(); ); .
};
แต่ถึงอย่างนี้ก็มีปัญหา จะเกิดอะไรขึ้นถ้า 3 เดือนจากนี้ Joe Coder สร้าง Doctor Employee แต่เขาลืมโทรไปที่ increment_money_earned () ใน do_work ()?
คำถาม:
เป็นกรณีที่ 3ดีกว่ากรณีที่ 1 ? เป็นเพราะ 'encapsulation ที่ดีกว่า' หรือ 'double loosely ที่มากกว่า' หรือด้วยเหตุผลอื่น?
เป็นกรณีที่ 3ดีกว่ากรณีที่ 2เพราะมันสอดคล้องกับแห้ง?