SOLID — От нуля до картошки 3

Mar 31 2023
О принципе замещения Лискова (LSP) Сегодня я продолжу рассказывать о принципе замещения Лискова (LSP) в этой статье, вы можете прочитать мою предыдущую статью о принципе единой ответственности и принципе Open/Closed (OCP) там. Прежде чем перейти к подробному объяснению LSP, мы должны знать, насколько LSP полезен в нашей повседневной работе.

О принципе замещения Лискова (LSP)

Сегодня я продолжу рассказывать о принципе замещения Лискова (LSP) в этой статье, вы можете прочитать мою предыдущую статью о принципе единой ответственности и принципе Open/Closed (OCP) там .

Прежде чем перейти к подробному объяснению LSP , мы должны знать, насколько LSP полезен в нашей повседневной работе. LSP помогает нам моделировать хорошие иерархии наследования. Это помогает нам предотвратить иерархии моделей, которые не соответствуют принципу открытости/закрытости. Любая модель наследования, которая придерживается принципа замещения Лискова , будет неявно следовать принципу открытости/закрытости .

Давайте перейдем к кодированию, кстати, если вы не понимаете, что такое kotlin, не волнуйтесь, LSP можно реализовать на любом языке, поэтому вы можете попробовать свой любимый.

У нас есть Studentкласс, в котором есть calculateGPAметод, вычисляющий средний балл на основе оценок учащегося:

open class Student(val grades: List<Double>) {
    open fun calculateGPA(): Double {
        // calculate the GPA based on the grades
    }
}

class HonorsStudent(grades: List<Double>) : Student(grades) {
    override fun calculateGPA(): Double {
        // calculate the GPA based on a different set of rules for honors students
    }
}

Чтобы придерживаться LSP , мы можем изменить дизайн классов. Один из способов сделать это — создать новый интерфейс с именем, GPAимеющим calculateметод:

interface GPA {
    fun calculate(): Double
}

open class Student(val grades: List<Double>) : GPA {
    override fun calculate(): Double {
        // calculate the GPA based on the grades
    }
}

class HonorsStudent(grades: List<Double>) : GPA {
    override fun calculate(): Double {
        // calculate the GPA based on a different set of rules for honors students
    }
}

Это соответствует принципу подстановки Лискова, потому что любому коду, который ожидает объект типа, GPAможет быть передан либо Studentобъект, либо HonorsStudentобъект, и поведение метода calculateбудет согласованным для обоих объектов.

Выделяя calculateGPAповедение в отдельный интерфейс, мы гарантируем, что любой подкласс, реализующий этот интерфейс, ведет себя согласованно с другими объектами этого типа интерфейса.

Спасибо, что нашли время прочитать эту статью. Я надеюсь, что мое письмо было информативным и наводящим на размышления.