Sobes.tech
Junior

SOLID prinsiplərində 'L' hərfi nə ilə əlaqədardır?

sobes.tech Süni İntellekt

AI-dan cavab

Barbary Liskov-un Əvəzləmə Prinsipi (Liskov Əvəzləmə Prinsipi).

Bu prinsipə görə, proqramdakı obyektlər onların alt tiplərinin nümunələri ilə əvəz oluna bilməlidir, proqramın düzgün işləməsinə təsir etmədən.

Başqa sözlə, əgər B sinfi A sinfinin alt tipidirsə, onda A tipli hər hansı obyekt proqramda B obyektinə dəyişdirilə bilər və proqram düzgün işləməyə davam edəcək.

Bu prinsip daha çevik və dəyişikliklərə davamlı memarlıq yaratmağa kömək edir, irsiyyətlə işləyərkən yan təsirləri minimuma endirir.

LSP-nin pozulması:

class Rectangle {
    var width: Double
    var height: Double

    init(width: Double, height: Double) {
        self.width = width
        self.height = height
    }

    var area: Double {
        return width * height
    }
}

class Square: Rectangle { // Kvadrat düzbucaqlının alt tipidir
    override var width: Double {
        didSet {
            height = width // En dəyişdikdə, hündürlük də dəyişir
        }
    }

    override var height: Double {
        didSet {
            width = height // Hündürlük dəyişdikdə, en də dəyişir
        }
    }

    init(side: Double) {
        super.init(width: side, height: side)
    }
}

func calculateArea(of rectangle: Rectangle) -> Double {
    return rectangle.area
}

let myRectangle = Rectangle(width: 5, height: 10)
print(calculateArea(of: myRectangle)) // 50

let mySquare = Square(side: 5)
// Bu, 5x5 ölçülü kvadrat və sahəsi 25 kimi qəbul edilir.
// Ancaq, `Rectangle` gözləyən funksiyada istifadə edilərkən,
// en və ya hündürlüyü dəyişdirsək,
// onun davranışı gözlənilməz ola bilər, çünki Square hər iki tərəfi eyni anda dəyişir.
// Bu nümunədə, əgər dəyişiklik etməsək,
// nəticə 25 olacaq, amma məsələn, mySquare.width = 10 etsək,
// sahə 100 olacaq, bu da `Rectangle` ilə işləyən kod üçün gözlənilməz ola bilər.
print(calculateArea(of: mySquare)) // 25

Nümunədə Square LSP-ni pozur, çünki bir ölçünü dəyişmək (width və ya height) digərini də dəyişir. Əgər Square obyektindən Rectangle gözləniləndə istifadə etsək, bu, gözlənilməz davranışlara səbəb ola bilər, çünki Rectangle ilə işləyən kod müstəqil tərəf dəyişikliklərini gözləyə bilər.

LSP-yə uyğun:

Bu halda LSP-yə riayət etmək üçün, irsiyyət yerinə kompozisiyanı istifadə etmək və ya Square üçün ümumi interfeys və ya protokol yaratmaq olar. Məsələn, sahəsi olan fiqurlar üçün ümumi interfeys və ya protokol yaradıb, onu RectangleSquare-də həyata keçirmək.

protocol Shape {
    var area: Double { get }
}

class Rectangle: Shape {
    var width: Double
    var height: Double

    init(width: Double, height: Double) {
        self.width = width
        self.height = height
    }

    var area: Double {
        return width * height
    }
}

class Square: Shape {
    var side: Double

    init(side: Double) {
        self.side = side
    }

    var area: Double {
        return side * side
    }
}

func calculateShapeArea(of shape: Shape) -> Double {
    return shape.area
}

let myShapeRectangle: Shape = Rectangle(width: 5, height: 10)
print(calculateShapeArea(of: myShapeRectangle)) // 50

let myShapeSquare: Shape = Square(side: 5)
print(calculateShapeArea(of: myShapeSquare)) // 25

İndi SquareRectangle ümumi Shape protokolunu həyata keçirir və hər iki sinfin obyektlərini Shape gözləyən yerlərdə istifadə edə bilərik, gözlənilən davranış pozulmadan.