首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

PHP面向对象五大原则之里氏替换原则(LSP)详解

本文实例讲述了PHP面向对象五大原则之里氏替换原则(LSP)。...LSP指出:子类类型必须能够替换掉它们的父类型、并出现在父类能够出现的任何地方。它指导我们如何正确地进行继承和派生,并合理地重用代码。...1)父类的方法都要在子类中实现或者重写,并且派生类只实现其抽象类中声明的方法,而不应当给出多余的方法定义或实现 2)在客户端程序中只应该使用父类对象而不应当直接使用子类对象,这样可以实现运行期绑定(动态多态...不过PHP对LSP的支持并不好,缺乏向上转型等概念,只能通过一些曲折的方法实现。对于这个原则,这里就不细讲了。 下面给出一个缓存的实现接口,用抽象类做基类,遵循LSP实现其设计。 LSP中代码的不仅仅是功能,还名手语意。试思考:白马可以代换马,而牛同样作为劳动力,可代换马否?高跟鞋也是鞋子,男人穿高跟鞋又是否能接受? 希望本文所述对大家PHP程序设计有所帮助。

65330
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    可能是最好的设计模式入门教程——里氏替换原则

    反过来的代换不成立,如一个方法method2接受BaseClass类型的子类对象sub为参数:method2(sub),那么一般而言不可以有method2(base),除非是重载方法。...里氏代换原则是实现开闭原则的重要方式之一,由于使用基类对象的地方都可以使用子类对象,因此在程序中尽量使用基类类型来对对象进行定义,而在运行时再确定其子类类型,用子类对象来替换父类对象。...在程序中尽量使用基类类型来对对象进行定义,而在运行时再确定其子类类型,用子类对象来替换父类对象 感觉是这个意思吧,父类已经实现的方便,子类尽量不要去重写,子类可以去实现父类里没有实现的方法?...不符合LSP的最常见的情况是,父类和子类都是可实例化的非抽象类,且父类的方法被子类重新定义,这一类的实现继承会造成父类和子类间的强耦合,也就是实际上并不相关的属性和方法牵强附会在一起,不利于程序扩展和维护...在父类和子类的具体行为中,必须严格把握继承层次中的关系和特征,将基类替换为子类,程序的行为不会发生任何变化。同时,这一约束反过来则是不成立的,子类可以替换基类,但是基类不一定能替换子类。

    1.5K31

    2022-09-20 里氏替换

    在使用父类定义的逻辑中,如果对于某个子类需要单独处理,那就不要让它成为子类。...如果子类不能完整地实现父类的方法,或者父类的某些方法在子类中已经发生“畸变”,则建议断开父子继承关系,采用依赖、聚集、组合等关系代替继承。...子类输入参数范围可以扩展 比如父类的方法参数是 HashMap,子类同名方法参数是 Map,方法名相同,参数类型不同,属于重载。...这样父类调用传一个 HashMap 参数,父类方法被执行,根据 LSP 原则,父类可以被替换为子类,还是执行子类从父类继承来的方法,即执行那个参数是 HashMap 的方法。 这是希望的。...如果父类参数是 Map,子类是 HashMap 相当于范围缩小,这样父类传参 HashMap,执行到参数是 Map 的方法,当父类被子类替换后,会执行到子类参数是 HashMap 的方法,而不是从父类继承的参数为

    21920

    【AI时代的设计模式:LSP原则的智能应用】

    因此,解决方案是确保在设计时遵循统一的行为契约,并抽象出合适的基类(如 BankCard),避免在子类中改变父类行为的预期。这才能保证子类在父类的替换场景中保持一致性,确保程序的正确性。 ️...下面我将遵循lsp原则,将信用卡和储蓄卡的共性抽取出来,都继承自同一个父类BanCard,使得在程序中可以 使用父类 BankCard 类型 来引用它们,而程序行为仍然是正确的。...虽然这两个类在具体行为上有所不同,但它们都继承自同一个父类 BankCard。这使得在程序中可以 使用父类 BankCard 类型 来引用它们,而程序行为仍然是正确的。...子类替换父类:指的是在程序中,我们可以将父类的对象替换为子类的对象,程序依然能正确执行,而不引发错误或不一致的行为。...(creditCard, 500); // 传入信用卡 } // 处理取款的方法,接受 BankCard 类型参数 public static void processWithdrawal

    7110

    深入理解设计模式六大原则

    里氏替换原则的规范: 子类必须完全实现父类的方法 在类中调用其他类时务必要使用父类或接口,如果不能使用父类或接口,则说明类的设计已经违背了LSP原则。...如果子类不能完整地实现父类的方法,或者父类的某些方法在子类中已经发生”畸变“,则建议断开父子继承关系,采用依赖、聚集、组合等关系代替继承。 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。...子类可以有自己的个性 子类中可以增加自己特有的方法。因为子类可能有比父类多的属性和行为,所以向下转型是不安全的,从LSP来看,就是有子类出现的地方父类未必就可以出现。...覆盖或实现父类的方法时参数可以被放大 LSP要求制定一个契约,就是父类或接口,这种设计方法也叫做Design by Contract。...覆写或实现父类的方法时输出结构可以被缩小 父类的一个方法的返回值是一个类型T,子类的相同方法(重载或覆写)的返回值为S,那么LSP就要求S必须小于或等于T。

    3.1K62

    PHP核心技术与最佳实践(一)

    ,禁止其被继承 ③优先考虑用组合关系提高代码的可重用性 ④子类是一种特殊的类型,而不只是父类的一个角色 ⑤子类扩展,而不是覆盖或者使父类的功能失效 ⑥底层代码多用组合,顶层/业务层代码多用继承 5.多态...①在设计方面充分应用“抽象”和“封装”的思想 ②在系统功能编程实现方面应用面向接口的编程 D.替换原则(LSP,里氏替换原则):子类必须能够替换成它们的基类 1.定义:子类型必须能够替换掉它们 的父类型...、并出现在父类能够出现的任何地方。...2.如何遵守: ①父类的方法都要在子类中实现或者重写,并且派生类只实现其抽象类中声明的方法,而不应该给出多余的方法定义或实现 ②在客户端程序 中只应该使用父类对象而不应当直接使用子类对象,这样可以实现运行期绑定...3.PHP对LSP的支持并不友好,缺乏向上转型等概念,只能通过一些曲折的方法实现。

    1.1K40

    软件工程设计原理里氏替换原则举例

    这个原则指出,如果类 S 是类 T 的子类型,则程序中使用 T 的对象的地方都可以不经修改地使用 S 的对象。换句话说,子类的对象应该能够替换掉它们的父类对象,而不影响程序的正确性。...这个原则强调了继承关系中的行为兼容性,保证了基类和派生类之间的正确抽象和继承关系。具体实现实现里氏替换原则的关键是确保子类的行为满足父类的行为契约。子类可以扩展父类的功能,但不应改变父类原有的功能。...这通常意味着:子类不应重写父类的非抽象方法。子类的方法应保持与父类方法相同的输入参数类型和返回类型。子类的方法不应抛出父类方法未声明的异常。...举例前的分析:不遵守LSP:子类重写父类方法,改变了原有功能的行为。遵守LSP:子类扩展父类功能,保持原有功能的行为不变。JAVA代码举例假设有一个几何形状的类和两个子类:矩形和正方形。...实践中的好处增强程序的可读性和可维护性:保证了基类和子类之间的一致性,使得代码更易于理解和维护。提高代码的可重用性:遵循LSP的设计使得子类可以在不改变原有功能的前提下,用于父类可以使用的任何场合。

    13810

    数组支持协变&逆变吗?泛型呢?

    OO(面相对象)六大设计原则之一的LSP(里氏代换原则 Liskov Substitution Principle),里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。...,同理基本类型封装类为Number类的子类,关于自动装箱和自动拆箱是java在JDK1.5的时候引入的新特性,我们这里不多讲,上面的代码可以正常编译,并且输出下面的内容,这里,数组里的基本类型装箱为封装类放到了堆中...//子类的doStuff()方法返回值的类型比父类方法要窄,即该方法为协变方法,也称多态。...:子类的方法返回值的类型比父类方法宽,此时为逆变方法。...虽然子类扩大了父类的输入返回参数,但是这里已经是重载了。

    70710

    泛型接口,泛型类和泛型通配符

    比如 public void add(E e); 这里的add方法并没有指定任何一个具体的类型,而是将类型也作为了参数,E是任何一个类型,e是任意类型E的实例。...比如父类是Book,子类不能直接extends Book,而是需要指定T的类型,上例中使用的Book作为类型。 在java中,泛型不能继承和实现。为什么?WHY?...使用泛型 由于方法中的泛型需要在定义类的时候就指定,所以如果需要使用含有泛型的方法,必须在创建该泛型类对象的时候就需要指定泛型类型,因为使用的时候必须指定类型,不论是普通参数还是泛型参数。...那为什么继承的时候也要确定泛型呢?因为继承就是在使用一个已经定义好的类,使用泛型类,就要指定类型。 3.用什么样的参数形式来接受List这种形式的参数?...>可以看做所有List的父类,Set可以看做所有Set的父类,使用?来表示一个未定义的类型,用来接受任何类型参数。 但是如果使用通配符,在部分功能上是会受到限制的。

    2.3K20

    面向对象设计原则-里氏替换原则

    LSP的定义LSP原则的正式定义是:“如果S是T的一个子类型,那么S对象可以替换T对象,而程序执行的结果不会发生变化。” 换句话说,一个子类必须能够完全替代其父类,且不会对程序的正确性造成任何影响。...LSP的重要性LSP的重要性体现在以下几个方面:(1)提高代码的可重用性由于子类必须能够替代其父类,因此我们可以在程序中重用父类的代码,而不需要在子类中重复编写相同的代码。...这样可以大大提高代码的可重用性。(2)减少出错的可能性如果子类不能够完全替代其父类,那么在程序执行过程中就可能会出现错误,这些错误可能会导致程序崩溃或者产生不可预料的结果。...因此,使用LSP可以减少出错的可能性,提高程序的稳定性。(3)提高程序的可扩展性如果我们遵循LSP原则,那么我们就可以轻松地在程序中添加新的子类,而不需要修改原有的代码。...LSP的实现方法在Java中,实现LSP的方法有以下几个方面:(1)子类必须实现父类的所有抽象方法如果一个父类是抽象类或者接口,那么它的所有子类必须实现父类的所有抽象方法。

    27710

    设计模式专题(一)——面向对象的设计原则

    主要需要实现以下内容: 1)定义接口,要求继承该接口的类都要实现query、where、order、from、select等方法; 2)定义工厂类,其中一个方法通过用户输入的数据库类型...二、接口隔离(ISP) 1、含义 接口隔离主要要求:客户端(如调用接口的类)不应被迫接受不需要的接口,导致被迫定义空方法;一个类对另一个类的依赖应建立在最小接口上。...2、最明显体现接口隔离的设计模式主要是装饰模式。 四、替换原则(LSP) 1、含义 替换原则要求:子类型必须能够替换父类型,并出现在父类型任何能出现的地方。...因此,满足LSP原则的类,要求基础父类的子类,要覆盖到父类的所有方法,即要求子类调用父类的方法,或者对父类中的方法进行重写。...其核心就是解耦,使各类之间的依赖度降低。 2、实现方式 在高层次的类中提出接口的声明,在低层次中实现接口;高层次的类通过抽象接口使用服务。

    1.3K120

    PHP7.0~PHP7.1~PHP7.2~PHP7.3~PHP7.4新特性

    > 复制代码 以上例程会输出: int(3) 复制代码 16.会话选项 session_start() 可以接受一个 array 作为参数, 用来覆盖 php.ini 文件中设置的 会话配置选项。...它的作用是控制 PHP 只有在会话中的数据发生变化的时候才 写入会话存储文件,如果会话中的数据没有发生改变,那么 PHP 会在读取完会话数据之后, 立即关闭会话存储文件,不做任何修改,可以通过设置 read_and_close...这可以被用在参数或者返回值类型中,它代表接受数组或者实现了Traversable接口的对象。...至于子类,当用作参数时,子类可以收紧父类的iterable类型到array 或一个实现了Traversable的对象。对于返回值,子类可以拓宽父类的 array或对象返回值类型到iterable。...不过这仍然是符合LSP,因为现在这种参数类型是逆变的。 <?

    15.3K21

    SOLID之LSP

    里氏代换原则 LSP,Liskov Substitution Principle 子类型必须能够替换掉它们的基类型 若对每个类型S的对象O1,都存在一个类型T的对象O2,使得在所有针对T编写的程序P中,...正是子类型的可替换性才使得使用基类类型的模块在无需修改的情况下就可以扩展,对于LSP的违反常常会导致以明显违反OCP的方式使用运行时类型辨别(RTTI),这种方式常常是使用一个显式的if语句或才if/else...同样假设B的某个派生类D,如果把D对象作为B类型传递给f,会导致f出现错误的行为。那么D就违反了LSP。显然,D对于f来说是脆弱的。...在OOD中IS-A关系是就行为方式而言,而不是属性,这也就是面向接口编程;派生类的行为方式和输出不能违反基类已经确立的任何限制。...基类的用户不应该被派生类的输出扰乱 简单判断就是“可替换性”,子类是否能替换父类并保持原有行为不变 LSP与架构 LSP从诞生开始,也就差不多这些内容,主要是指导如何使用继承关系的一种方法。

    71630

    Java 程序员应在2019年学习的10条面向对象(OOP)设计原则

    因此请当心这种耦合,不要将任何使用相似代码但无关的东西组合在一起。 2.封装变化 在软件领域中只有一件事是不变的,即 “更改”。因此,封装您期望或怀疑将来会更改的代码。...你们中的某些人可能会争论这一点,但我发现 Composition 比 Inheritance灵活得多。...7.Liskov替代原则(LSP) 根据 Liskov 替换原则,子类型必须可以替换为父类型,即使用父类类型的方法或函数必须能够与子类的对象一起工作而没有任何问题。”...LSP 与单职责原则和接口隔离原则密切相关。如果一个类具有比子类更多的功能,则可能不支持某些功能并且确实违反了 LSP。...9.使用接口而不是实现 始终使用接口而不是使用实现编程,这将导致灵活的代码可以与任何新的接口实现一起使用。 因此,在Java中对变量,方法的返回类型或方法的参数类型使用接口类型。

    54530

    为什么一个类不能随意被继承?

    里氏替换原则(Liskov Substitution Principle,LSP)可以解释为: 派生类型(子类)必须能够替换掉它们的基类型(父类)。...上一篇文章中,我们提到开闭原则的最佳实践之一是抽象化。有了抽象,我们就可以基于抽象写一些具体的实现类了--这就是基类(父类)和派生类(子类)的继承关系。 好啦!...问题来啦~ 请问“这个继承关系可以随便使用吗?” 从语法上来说,怎么用 extends 关键字来实现父子类关系都可以!但从业务逻辑上看,这是有很大问题的。比如下面这个例子。...因为,你把 Cat 给邻居,邻居会觉得你在鄙视他:咋的?古有指鹿为马,今有“借狗给猫”? 小伙伴们,肯定就会说啦:Cat 和 Dog 是两种动物了,肯定不能使用继承关系啦~ 这个说法是对的。...但对于我们面向对象编程过程中,尤其是在“继承”关系中,我们考虑的是“替换性”。Cat 不能替换 Dog, 因此,我们不能让 Cat extends Dog。

    20920

    我不允许还有人不知道SOLID原则

    里氏替换原则(LSP) 据说这是大多数开发人员最难理解的原则。这是由芭芭拉·利斯科夫(Barbara Liskov)介绍的。它适用于继承,子类必须完全可替换其父类。...如果类 A 是类 B 的子类型,那么我们应该能够在不中断程序行为的情况下用 A 替换 B。 让我们通过一个例子来理解这一点,但是我要提醒你,这个原则会让文章变得很长。...WhatsApp 类是 SocialMedia 类的子类,那么我们应该能够在不中断程序行为的情况下用 WhatsApp 替换 SocialMedia。...我们有一个支付接口来代表所有类型的支付。BankPayment 和 LoanPayment 是 Payment 中实现类。...我们的新购物中心现在将能够使用任何银行卡,而不是与特定的卡类型紧密结合!请参阅下面的客户端代码。

    25020

    面试官:设计原则有哪些?什么是里式替换原则?

    继承必须确保父类所拥有的性质在子类中仍然成立。...任何基类可以出现的地方,子类一定可以出现。...M416都实现了kill()方法,但是ToyGun因为是玩具枪,它没有杀伤力,所以,无法实现kill(),那么针对这种情况,即:子类不能完整的实现父类的方法,或者父类的某些方法在子类中已经发生了“畸变”...4> 当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格,编译上也会提示有问题 2.3> 最佳实践 不符合LSP的最常见的情况是,父类和子类都是可实例化的非抽象类,且父类的方法被子类重新定义...3> 在泛型的使用中,参数List与List在经过类型擦除后,是相同参数。

    23030

    设计模式—–里氏替换原则

    它必须知道所有 Shape 基类的衍生子类,并且当有新的子类被创建时就必须修改这个函数。事实上,很多人看到这个函数的结构都认为是在诅咒面向对象设计。...这里明确地违背了 LSP 原则,此函数在衍生对象为参数的条件下无法正常工作。...而失败的原因是因为在父类 Rectangle 中没有将 SetWidth 和 SetHeight 设置为 virtual 函数。 我们也能很容易的解决这个问题。...契约式设计(Design by Contract) Bertrand Meyer 在 1988 年阐述了 LSP 原则与契约式设计之间的关系。使用契约式设计,类中的方法需要声明前置条件和后置条件。...换句话说,当通过基类接口使用对象时,客户类仅知道基类的前置条件和后置条件。因此,衍生类对象不能期待客户类服从强于基类中的前置条件。也就是说,它们必须接受任何基类可以接受的条件。

    92030

    【愚公系列】2023年11月 面向对象设计原则(三)-里氏替换原则(Liskov Substitution Principle or LSP)

    换句话说,这个原则要求子类必须能够完全替换父类,并且子类在替换父类的过程中,不改变原有的程序行为。 这样做可以确保代码的可维护性、可扩展性和代码的可重用性。...里氏替换原则根据“运行时子类对象覆盖父类对象”的特点,可以很方便的对系统进行扩展,只需要增加子类而无需更改任何现有代码。...例如增加一个新的正方形子类Square,而不需要对DoSomething方法做任何改动。...1.子类必须完全实现父类的方法2.子类可以有自己的个性:从里氏替换原则来看,就是有子类出现的地方父类未必就可以出现。...3.覆盖或实现父类的方法时输入参数可以被放大覆写或实现父类的方法时输出结果可以被缩小在项目中,采用里氏替换原则时,尽量避免子类的“个性”,一旦子类有“个性”,这个子 类和父类之间的关系就很难调和了,把子类当做父类使用

    23621
    领券