חקר עקרון ההחלפה של ליסקוב

המונח SOLID הוא ראשי תיבות פופולריים המשמשים להתייחסות למכלול של חמישה עקרונות של ארכיטקטורת תוכנה. אלה כוללים: SRP (אחריות יחידה), פתיחה / סגירה, החלפת ליסקוב, הפרדת ממשק והיפוך תלות.

LSP (Principle Substitution Principle) הוא עקרון בסיסי של OOP וקובע כי שיעורים נגזרים אמורים להיות מסוגלים להרחיב את מחלקות הבסיס שלהם מבלי לשנות את התנהגותם. במילים אחרות, מחלקות נגזרות צריכות להיות ניתנות להחלפה עבור סוגי הבסיס שלהן, כלומר, יש להחליף התייחסות למחלקת בסיס במחלקה נגזרת מבלי להשפיע על ההתנהגות. עקרון ההחלפה של ליסקוב מייצג סוג משנה התנהגותי חזק והוצג על ידי ברברה ליסקוב בשנת 1987.

לדברי ברברה ליסקוב, "מה שרוצים כאן זה משהו כמו מאפיין ההחלפה הבא: אם לכל אובייקט o1 מסוג S יש אובייקט o2 מסוג T כך שלכל התוכניות P מוגדרות במונחים של T, ההתנהגות של P הוא ללא שינוי כאשר o1 מוחלף ל- o2 אז S הוא תת-סוג של T. "

דוגמא קלאסית להפרת עקרון החלפת ליסקוב היא בעיית המלבן - הריבוע. הכיתה הריבועית מרחיבה את מחלקת המלבן ומניחה שהרוחב והגובה שווים.

שקול את הכיתה הבאה. מחלקת המלבן מכילה שני איברי נתונים - רוחב וגובה. ישנם גם שלושה מאפיינים - גובה, רוחב ושטח. בעוד ששני המאפיינים הראשונים קובעים את הגובה והרוחב של המלבן, למאפיין Area יש גטר שמחזיר את שטח המלבן.

 class Rectangle

    {

        protected int width;

        protected int height;

         public virtual int Width

        {

            get

            {

                return width;

            }

            set

            {

                width = value;

            }

        }

 

        public virtual int Height

        {

            get

            {

                return height;

            }

            set

            {

                height = value;

            }

        }

               

       public int Area

        {

            get

            {

                return height * width;

            }

         }    

    }

ריבוע הוא סוג של מלבן שכל צלעותיו שוות בגודלן, כלומר הרוחב והגובה של ריבוע זהים.

class Square : Rectangle

    {

        public override int Width

        {

            get

            {

                return width;

            }

            set

            {

                width = value;

                height = value;

            }

        }

        public override int Height

        {

            get

            {

                return width;

            }

            set

            {

                width = value;

                height = value;

            }

        }

    }

 שקול מחלקה אחרת בשם ObjectFactory.

 class ObjectFactory

    {

        public static Rectangle GetRectangleInstance()

        {

            return new Square();

        }

    }

שים לב שקובעי המאפיינים של מאפייני רוחב וגובה במחלקה המרובעת עוקפו ושונו כדי להבטיח שהגובה והרוחב זהים. בואו ניצור מופע של מחלקת המלבן באמצעות נקבע את מאפייני הגובה והרוחב שלו.

Rectangle s = ObjectFactory.GetRectangleInstance();

s.Height = 9;

s.Width = 8;

Console.WriteLine(s.Area);

קטע הקוד שלמעלה בעת ביצועו יציג את הערך 64 במסוף. הערך הצפוי הוא 72 מכיוון שהרוחב והגובה שהוזכרו הם 9 ו- 8 בהתאמה. זו הפרה של עקרון ההחלפה של ליסקוב. הסיבה לכך היא שהמחלקה המרובעת שהרחיבה את מחלקת המלבן שינתה את ההתנהגות. כדי להבטיח כי עקרון ההחלפה של ליסקוב אינו מופר, מחלקת הריבוע יכולה להרחיב את מחלקת המלבן אך אינה צריכה לשנות את ההתנהגות. ההתנהגות שונתה על ידי שינוי הקובעים הן עבור המאפיינים רוחב והן גובה. ערכי הגובה והרוחב זהים אם זה ריבוע - הם לא צריכים להיות זהים אם זה מלבן.

כיצד נתקן זאת, קרי, נבטיח שלא יופר על עקרון זה? ובכן, ניתן להציג מחלקה חדשה בשם רב-צדדית ולהבטיח שגם הכיתת מלבן וגם הכיתות המרובעות מרחיבות את המעמד הרב-צדדי.

 public class Quadrilateral

    {

        public virtual int Height { get; set; }

        public virtual int Width { get; set; }

        public int Area

        {

            get

            {

                return Height * Width;

            }

        }

    } 

כעת, הן הכיתות מלבן והן ריבוע צריכות להרחיב את הכיתה המרובעת ולהגדיר את הערכים של מאפייני רוחב וגובה כראוי. בעיקרו של דבר, המחלקות הנגזרות צריכות להיות בעלות הפונקציונליות הנחוצה להגדרת ערכים למאפיינים אלה בהתבסס על סוג המופע המרובע שעליו עליכם לחשב שטח. שים לב שתכונות הגובה והרוחב סומנו כווירטואליות במחלקה המרובעת, כלומר יש להחליף מאפיינים אלה על ידי המחלקות שמקורן המחלקה הרביעית.

עקרון ההחלפה של ליסקוב הוא הרחבה של עקרון ה- Open Close והוא מופר כאשר כתבת קוד שזורק "חריגים שלא מיושמים" או שאתה מסתיר שיטות במחלקה נגזרת שסומנו כווירטואליות במחלקת הבסיס. אם הקוד שלך עומד בעקרון החלפת ליסקוב יש לך יתרונות רבים. אלה כוללים: שימוש חוזר בקוד, צימוד מופחת ותחזוקה קלה יותר.