您能用一个很好的 C# 示例来解释里氏替换原理吗? [关闭]

2023-12-15

您能用一个很好的 C# 示例来解释里氏替换原理(SOLID 的“L”),以简化的方式涵盖该原理的所有方面吗?如果真的可以的话。


(此答案已于2013-05-13重写,请阅读评论底部的讨论)

LSP 是关于遵循基类的契约。

例如,您可以不在子类中抛出新的异常,因为使用基类的异常不会发生这种情况。如果基类抛出同样的情况ArgumentNullException如果缺少参数并且子类允许该参数为空,则也是 LSP 违规。

下面是一个违反 LSP 的类结构的示例:

public interface IDuck
{
   void Swim();
   // contract says that IsSwimming should be true if Swim has been called.
   bool IsSwimming { get; }
}

public class OrganicDuck : IDuck
{
   public void Swim()
   {
      //do something to swim
   }

   bool IsSwimming { get { /* return if the duck is swimming */ } }
}

public class ElectricDuck : IDuck
{
   bool _isSwimming;

   public void Swim()
   {
      if (!IsTurnedOn)
        return;

      _isSwimming = true;
      //swim logic            
   }

   bool IsSwimming { get { return _isSwimming; } }
}

以及调用代码

void MakeDuckSwim(IDuck duck)
{
    duck.Swim();
}

正如您所看到的,有两个鸭子的例子。一只有机鸭子和一只电动鸭子。电动鸭子只有在打开的情况下才能游泳。这打破了 LSP 原则,因为必须打开它才能像IsSwimming(这也是合同的一部分)不会像基类中那样设置。

你当然可以通过这样做来解决它

void MakeDuckSwim(IDuck duck)
{
    if (duck is ElectricDuck)
        ((ElectricDuck)duck).TurnOn();
    duck.Swim();
}

但这会破坏开放/封闭原则,并且必须在任何地方实现(因此仍然会生成不稳定的代码)。

正确的解决方案是自动打开鸭子Swim方法,并通过这样做使电动鸭子的行为完全按照定义IDuck界面

Update

有人添加了评论并删除了它。我想提出一个有效的观点:

解决方案是打开鸭子里面Swim方法在实际实现时可能会产生副作用(ElectricDuck)。但这可以通过使用来解决显式接口实现。恕我直言,如果不打开它,您更有可能会遇到问题Swim因为预计它在使用时会游泳IDuck界面

Update 2

重新表述了一些部分,使其更加清晰。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

您能用一个很好的 C# 示例来解释里氏替换原理吗? [关闭] 的相关文章

  • 提交后禁用按钮

    当用户提交付款表单并且发布表单的代码导致 Firefox 中出现重复发布时 我试图禁用按钮 去掉代码就不会出现这个问题 在firefox以外的任何浏览器中也不会出现这个问题 知道如何防止双重帖子吗 System Text StringBui
  • 复制 std::function 的成本有多高?

    While std function是可移动的 但在某些情况下不可能或不方便 复制它会受到重大处罚吗 它是否可能取决于捕获变量的大小 如果它是使用 lambda 表达式创建的 它依赖于实现吗 std function通常被实现为值语义 小缓
  • C中的malloc内存分配方案

    我在 C 中尝试使用 malloc 发现 malloc 在分配了一些内存后浪费了一些空间 下面是我用来测试 malloc 的一段代码 include
  • 在 LINQ 中按 Id 连接多表和分组

    我想按categoryId显示列表产品的名称组 这是我的代码 我想要我的视图显示结果 Desktop PC HP Red PC Dell Yellow PC Asus Red SmartPhone Lumia 720 Blue 我的组模型
  • 复制目录内容

    我想将目录 tmp1 的内容复制到另一个目录 tmp2 tmp1 可能包含文件和其他目录 我想使用C C 复制tmp1的内容 包括模式 如果 tmp1 包含目录树 我想递归复制它们 最简单的解决方案是什么 我找到了一个解决方案来打开目录并读
  • java.io.Serialized 在 C/C++ 中的等价物是什么?

    C C 的等价物是什么java io Serialized https docs oracle com javase 7 docs api java io Serializable html 有对序列化库的引用 用 C 序列化数据结构 ht
  • 如何使用 LINQ2SQL 连接两个不同上下文的表?

    我的应用程序中有 2 个数据上下文 不同的数据库 并且需要能够通过上下文 B 中的表的右连接来查询上下文 A 中的表 我该如何在 LINQ2SQL 中执行此操作 Why 我们正在使用 SaaS 产品来跟踪我们的时间 项目等 并希望向该产品发
  • 在 Visual Studio 2010 中从 Fortran 调用 C++ 函数

    我想从 Fortran 调用 C 函数 为此 我在 Visual Studio 2010 中创建了一个 FORTRAN 项目 之后 我将一个 Cpp 项目添加到该 FORTRAN 项目中 当我要构建程序时出现以下错误 Error 1 unr
  • qdbusxml2cpp 未知类型

    在使用 qdbusxml2cpp 程序将以下 xml 转换为 Qt 类时 我收到此错误 qdbusxml2cpp c ObjectManager a ObjectManager ObjectManager cpp xml object ma
  • 是否有实用的理由使用“if (0 == p)”而不是“if (!p)”?

    我倾向于使用逻辑非运算符来编写 if 语句 if p some code 我周围的一些人倾向于使用显式比较 因此代码如下所示 if FOO p some code 其中 FOO 是其中之一false FALSE 0 0 0 NULL etc
  • 具有交替类型的可变参数模板参数包

    我想知道是否可以使用参数包捕获交替参数模式 例如 template
  • 我可以使用 moq Mock 来模拟类而不是接口吗?

    正在经历https github com Moq moq4 wiki Quickstart https github com Moq moq4 wiki Quickstart 我看到它 Mock 一个接口 我的遗留代码中有一个没有接口的类
  • 如何检测表单的任何控件的变化?

    如何检测 C 中表单的任何控件的更改 由于我在一个表单上有许多控件 并且如果表单中的任何控件值发生更改 我需要禁用按钮 我正在寻找一些内置函数 事件处理程序 属性 并且不想为此创建自定义函数 不 我不知道任何时候都会触发任何事件any控制表
  • CMake 无法确定目标的链接器语言

    首先 我查看了this https stackoverflow com questions 11801186 cmake unable to determine linker language with c发帖并找不到解决我的问题的方法 我
  • 使用管道时,如果子进程数量大于处理器数量,进程是否会被阻塞?

    当子进程数量很大时 我的程序停止运行 我不知道问题是什么 但我猜子进程在运行时以某种方式被阻止 下面是该程序的主要工作流程 void function int process num int i initial variables for
  • 动态添加 ASP.Net 控件

    我有一个存储过程 它根据数据库中存储的记录数返回多行 现在我想有一种方法来创建 div 带有包含该行值的控件的标记 如果从数据库返回 10 行 则 10 div 必须创建标签 我有下面的代码来从数据库中获取结果 但我不知道如何从这里继续 S
  • 将 MQTTNet 服务器与 MQTT.js 客户端结合使用

    我已经启动了一个 MQTT 服务器 就像this https github com chkr1011 MQTTnet tree master例子 该代码托管在 ASP Net Core 2 0 应用程序中 但我尝试过控制台应用程序 但没有成
  • 从 Excel 应用程序对象中查找位数(32 位/64 位)?

    是否可以从 Microsoft Office Interop Excel ApplicationClass 确定 Excel 是以 32 位还是 64 位运行 Edit该解决方案应该适用于 Excel 2010 和 Excel 2007 此
  • 如何部署“SQL Server Express + EF”应用程序

    这是我第一次部署使用 SQL Server Express 数据库的应用程序 我首先使用实体 框架模型来联系数据库 我使用 Install Shield 创建了一个安装向导来安装应用程序 这些是我在目标计算机中安装应用程序所执行的步骤 安装
  • 从列表中选择项目以求和

    我有一个包含数值的项目列表 我需要使用这些项目求和 我需要你的帮助来构建这样的算法 下面是一个用 C 编写的示例 描述了我的问题 int sum 21 List

随机推荐

  • Matlab:是否有一个函数可以定位数字中的“n”位(即“75673”中的第二位数字,所以5)

    我有一个号码A 7654321 我需要位置 5 处的数字 从开头算起 或从末尾算起的数字 3 在本例中为 3 是否有一个函数可以执行以下操作 getdigit A n 其中 A 是数字 n 是我想要的数字的位置 我可以将数字转换为文本字符串
  • 仍然无法理解 ASP.NET 事件。他们有什么意义?

    也许我很慢 但我只是不明白为什么你会使用不是从实际操作 例如单击 派生的事件 当您只需调用方法时 为什么要经历创建委托和事件的繁琐工作呢 看起来 当您创建一个事件时 您所做的只是创建一种方法 让调用者通过一些复杂的过程来调用一个简单的方法
  • 如何将 ASP.NET 下拉列表 DataTextField 属性绑定到嵌套属性

    我想绑定DataTextFieldASP NET 下拉控件的属性到作为初始数据源的属性的对象的属性 我将如何完成这项特定任务 下拉数据源数据架构 public class A public string ID get set public
  • ajax请求后页面刷新

    好吧 我有一个简单的表格 仅包含一个text field 当我们点击提交时 写入文本字段的数据将存储在数据库中 通过ajax存储 ajax 工作正常并且数据已提交 但是页面会自动刷新并且 URL 包含输入字段的内容 我的表格
  • 我应该使用多个数据库吗?

    我即将使用 Ruby on Rails 创建一个应用程序 我想使用多个数据库 基本上是一个会计应用程序 每个用户都有多个公司 我想为每个公司创建一个数据库 我找到了这个帖子http programmerassist com article
  • Fiware - 上下文代理:NGSIv2 订阅问题

    我正在使用 Orion 上下文代理版本 1 2 0 我使用 NGSIv2 订阅了两个不同的 cygnus 0 11 和 0 13 如下 curl 172 21 0 23 1026 v2 subscriptions s S header Fi
  • 查找重复的图像文件

    我的硬盘中存储了大约 1 TB 的图像 这些是朋友和家人长时间拍摄的照片 从某种意义上说 这些图片中的许多都是重复的 相同的文件保存在不同的位置 可能也具有不同的名称 我想问是否有任何工具 实用程序或方法 我可以编写一个 来找出重复的文件
  • 如何使 rush 与我的 orionInstance 一起工作

    按照我之前的问题如何在 MapViewer 小部件中显示来自 OrionContextBroker 的实体我使用 Rush 配置了我的上下文代理实例 并且正在使用https ngsiproxy lab fi ware org作为 NGSI
  • 如何使用java并发编程的ExecutorService?

    我使用下面的代码在远程服务器上上传图像 当我使用下面的代码时 它会同时在远程服务器上上传所有图像 List
  • 排序功能未按预期工作

    我有一个对象数组 实际上是从后端获取的 现在我正在映射数据 并希望通过单击按钮按升序和降序对其进行排序 所以我创建了一个 onSort 函数 但它不起作用我预计 因为大写和小写问题存在 即使按字母顺序排列 最后显示小写 数字没有排序 还有另
  • 如何在单元格选择/取消选择时正确切换 UITableViewCellaccessoryType?

    我正在尝试切换配件类型当选择 取消选择表格单元格时 行为应该是 点击 gt 将accessoryType 设置为UITableViewCellAccessory复选标记 gt 再次点击单元格 gt 回滚到UITableViewCell 附件
  • .NET 4.5 SslStream - 取消异步读/写调用?

    有没有办法取消 SslStream 上的异步读取或写入任务 我尝试为 ReadAsync 提供 CancellationToken 但它似乎不起作用 当以下代码达到超时 Task Delay 时 它会调用 CancellationToken
  • 为 python 2 和 python 3 安装 scipy

    I used sudo apt get install python scipy安装 scipy 这将所有文件放入 usr lib python2 7 dist packages scipy 我最好的猜测是它选择该位置是因为 python
  • Javascript重新声明的全局变量覆盖旧值

    前几天我遇到了一个有趣的问题 想知道是否有人可以解释为什么会发生这种情况 这是我正在做的事情 出于本示例的目的 我稍微简化了示例 我正在使用方括号表示法创建一个全局范围的变量并为其分配一个值 后来我声明了一个与上面刚刚创建的变量同名的变量
  • 为什么 AutoResize 不适用于 C# 中 DataGridView 中的行标题宽度?

    我是 DataGridView 控件的新手 它让我很困惑 我遇到的问题是行标题宽度与其中的文本不太适合 我确实进行了搜索 但当前存在的解决方案并没有给我带来我所期望的结果 我正在使用此代码动态创建 DataGridView DataGrid
  • 成员变量可以用来初始化初始化列表中的其他成员吗?

    考虑以下 简化的 情况 class Foo private int evenA int evenB int evenSum public Foo int a int b evenA a a 2 evenB b b 2 evenSum eve
  • 如何将最小 DatePicker 日期设置为当前日期

    我想将用户可以在 DatePicker 中选择的最小日期设置为当前日期 我试过这个 DatePicker datePicker DatePicker findViewById R id event date datePicker setMi
  • 使用Python将数据加载到Mysql中

    可以用Python为Mysql建表吗 这是我的问题 我有一堆 txt 文件 我想将它们加载到 Mysql 数据库中 是否可以在 Python 中完成以下操作 而不是在 phpmyadmin 中手动创建表 创建表 包括数据类型定义 一一加载许
  • 在自定义对象上使用 ELKI 并理解结果

    我正在尝试使用ELKI的SLINK实现我的程序中的层次聚类 我有一组需要聚类的对象 属于我自己的类型 为此 我在聚类之前将它们转换为特征向量 这就是我目前让它运行并产生一些结果的方式 代码在 Scala 中 val clusterer ne
  • 您能用一个很好的 C# 示例来解释里氏替换原理吗? [关闭]

    Closed 这个问题需要多问focused 目前不接受答案 您能用一个很好的 C 示例来解释里氏替换原理 SOLID 的 L 以简化的方式涵盖该原理的所有方面吗 如果真的可以的话 此答案已于2013 05 13重写 请阅读评论底部的讨论