Mille eest vastutab täht 'L' SOLID põhimõtetes?
sobes.tech AI
Vastus AI-lt
Liskovi asenduspõhimõte (Liskov Substitution Principle).
Selle põhimõtte kohaselt peavad programmis olevad objektid olema asendatavad nende alamklasside eksemplaridega ilma programmi õigsust muutmata.
Teisisõnu, kui klass B on klassi A alamklass, siis võib iga A tüüpi objekt programmis olla asendatud B tüüpi objektiga ning programm jätkab korrektset tööd.
See põhimõte aitab luua paindlikumat ja muutustele vastupidavamat arhitektuuri, minimeerides kõrvaltoimeid pärilikkuse kasutamisel.
LSP rikkumine:
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 { // Ruut on ristküliku alamklass
override var width: Double {
didSet {
height = width // Laiuse muutmine muudab ka kõrgust
}
}
override var height: Double {
didSet {
width = height // Kõrguse muutmine muudab ka laiust
}
}
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)
// Oletame, et see on 5x5 ristkülik, mille pindala on 25.
// Kuid kasutades funktsioonis, mis ootab `Rectangle`-i,
// võib selle käitumine olla ettearvamatu, kui muuta laiust või kõrgust
// enne `calculateArea` väljakutset, kuna `Square` muudab mõlemad küljed korraga.
// Selles näites, kui mitte muuta omadusi pärast initsialiseerimist,
// on tulemus 25, kuid kui näiteks seame mySquare.width = 10
// enne `calculateArea` väljakutset, muutub selle pindala 100-ks, mis võib olla
// ootamatu `Rectangle`-iga töötavale koodile.
print(calculateArea(of: mySquare)) // 25
Selles näites rikub Square LSP-d, kuna ühe mõõtme (width või height) muutmine muudab ka teise. Kui kasutame Square objekti seal, kus oodatakse Rectangle-i, võib see viia ootamatu käitumiseni, kuna Rectangle-i kood võib eeldada, et küljed saavad muutuda sõltumatult.
LSP järgimine:
Selleks, et järgida LSP-d selles olukorras, võib jagada hierarhia või kasutada kompositsiooni mantoimise asemel Square-i jaoks. Näiteks võib luua ühise liidese või protokolli kujutiste jaoks, millel on pindala, ning rakendada seda Rectangle ja Square-is.
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
Nüüd rakendavad Square ja Rectangle ühise protokolli Shape, ning saame kasutada mõlema klassi objekte seal, kus oodatakse Shape-i, ilma et rikuksime oodatavat käitumist.