Sobes.tech
Junior

SOLID tamoyillarida 'L' harfi nima uchun javobgardir?

sobes.tech AI

AIdan javob

Barbara Liskovning o'rnash prinsipi (Liskov o'rnash prinsipi).

Ushbu prinsipga ko'ra, dasturdagi obyektlar ularning podtiplarining nusxalari bilan almashtirilishi mumkin bo'lishi kerak, bu dastur to'g'riligini o'zgartirmasdan.

Boshqacha qilib aytganda, agar B sinfi A sinfining podtipi bo'lsa, unda dasturdagi har qanday A turidagi obyekt B turidagi obyekt bilan almashtirilishi mumkin va dastur to'g'ri ishlashda davom etadi.

Ushbu prinsip meros bilan ishlashda yon ta'sirlarni minimallashtirish orqali yanada moslashuvchan va chidamli arxitektura yaratishga yordam beradi.

LSP buzilishi:

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, to'g'ri to'rtburchakning podtipi
    override var width: Double {
        didSet {
            height = width // Kenglik o'zgarganda, balandlik ham o'zgaradi
        }
    }

    override var height: Double {
        didSet {
            width = height // Balandlik o'zgarganda, kenglik ham o'zgaradi
        }
    }

    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 maydonli to'rtburchak deb faraz qilamiz.
// Ammo uni `Rectangle` kutayotgan funksiyada ishlatishda,
// uning xatti-harakatlari kutilmagan bo'lishi mumkin, agar kenglik yoki balandlik o'zgartirilsa,
// `calculateArea` chaqirilishidan oldin, chunki Square ikkala tomonini ham bir vaqtning o'zida o'zgartiradi.
// Bu misolda, agar faqat boshlang'ichdan keyin xususiyatlar o'zgartirilmasa,
// natija 25 bo'ladi, lekin agar, masalan, mySquare.width = 10
// `calculateArea` chaqirilishidan oldin, uning maydoni 100 bo'ladi, bu
// Rectangle bilan ishlovchi kod uchun kutilmagan bo'lishi mumkin.
print(calculateArea(of: mySquare)) // 25

Misolda, Square LSPni buzadi, chunki bir o'lchov (width yoki height) o'zgartirilganda, ikkinchisi ham o'zgaradi. Agar Square obyekti, Rectangle kutilgan joyda ishlatilsa, bu kutilmagan xatti-harakatlarga olib kelishi mumkin, chunki Rectangle bilan ishlovchi kod, tomonlarning mustaqil o'zgarish imkoniyatini faraz qilishi mumkin.

LSP ga mos kelishi:

Bu holatda LSP ni bajarish uchun, merosni bo'lish yoki Square uchun kompozitsiyani ishlatish mumkin. Masalan, maydonga ega bo'lgan shakllar uchun umumiy interfeys yoki protokol kiritish va uni Rectangle va Square da amalga oshirish.

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

Endi, Square va Rectangle umumiy Shape protokolini amalga oshiradi, va biz har ikkala sinf ob'ektlarini, Shape kutayotgan joyda ishlatishimiz mumkin, bu esa kutilgan xatti-harakatlarni buzmaydi.