使用更多派生类型覆盖子类继承的属性

2024-03-28

我想要实现的目标的简化示例如下所示:

public class Animal
{
    public virtual Teeth teeth {get;set;}
}

public class Mouse : Animal
{
    public override SmallTeeth teeth {get; set;} // SmallTeeth Inherits from Teeth
}

这显然不起作用,因为牙齿必须与 Animal 类中的类型相同才能在 Mouse 类中覆盖。但是,可以实现这样的事情吗?允许我在从 Animal 继承的任何函数中使用更多派生类型吗?例如,如果 Animal 类包含一个咬合函数:

public void Bite()
{
    teeth.bite()
    Console.WriteLine("Ouch")
} 

我可以打电话给Bite()从 Animal 继承的函数,它将使用 Mouse 类的 type 字段SmallTeeth。这可能吗?这是做我想做的事情的最好方法吗?如果不是,解决这个问题的正确方法是什么?


注意:这个答案写于 2016 年。从那时起,返回类型协方差就被添加到了 C# 中(令人惊讶!)。阅读此答案时请记住这一点。


你想要的功能叫做返回类型协方差,而 C# 不支持。 (顺便说一下,C++ 确实如此。)

协变返回类型的常见情况是:

abstract class Animal
{
    public abstract Cage GetCage();
}
public class Fish : Animal
{
    public override Aquarium GetCage() { ... }
}

这是不合法的,但如果合法那就是safe。也就是说,如果你手上有一只动物,并且你要求一个笼子,你就会得到一个,即使它是一条鱼。为什么?因为水族馆是一种笼子。

您的提议不仅非法,而且不安全:

Animal animal = new Mouse();
animal.Teeth = new TRexTeeth();

合同规定,可以用任何种类的牙齿调用二传手。通过使派生类在可接受的内容方面更加严格,您违反了基类的约定。

所以不要这样做。

不过,您可以通过多种方法在 C# 中实现您想要的目标。

这只是其中之一:

interface IAnimal
{
    Teeth Teeth { get; } // READ ONLY
}

class Mouse : IAnimal
{
    private SmallTeeth smallTeeth;
    public SmallTeeth Teeth 
    {
        get { return smallTeeth; }
    }

    Teeth IAnimal.Teeth { get { return this.Teeth; } }
}

现在,如果您将鼠标投射到 Animal 上,您将获得返回 Teeth 的属性,如果您正常使用鼠标,您将获得返回 Small Teeth 的属性。

我在这里描述了解决这个问题的另一种方法:

C# 支持返回类型协方差吗? https://stackoverflow.com/questions/5709034/does-c-sharp-support-return-type-covariance/5709191#5709191

其他答案中给出的通用解决方案也有效,尽管我个人更喜欢将泛型排除在外,除非有必要。

搜索“C# 中的返回类型协方差”以获取有关此模式的更多信息。

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

使用更多派生类型覆盖子类继承的属性 的相关文章

随机推荐

  • “user-images.githubusercontent.com”上的图像可以删除吗?

    我不小心在 GitHub 上上传了一张我不想放的图片 我原以为出于示例目的 我已经从上传的图像中删除了私人信息 但私人信息仍然存在 它包含诸如主机名之类的内容 我希望这些内容不是公开的 有没有办法从 github 的图像注册表中删除该图像
  • 到本地主机的 New-PSSession 失败

    我有一个打开本地主机远程会话的脚本 我需要这个来从登录脚本中在某些设备上安装 NuGet Username Admin Password ConvertTo SecureString adminPW AsPlainText Force ad
  • getElementsByClassName onclick 问题[重复]

    这个问题在这里已经有答案了 我在用着罗伯特 尼曼的 http robertnyman com 2008 05 27 the ultimate getelementsbyclassname anno 2008 脚本来获取文档中具有相同类的所有
  • 使用非 root 且无需 CPAN 安装 Perl 模块和依赖项

    我一直在为我的工作编写 Perl 脚本 而我工作的机器使安装 Perl 模块变得困难 我们不能有gcc出于安全原因 在我的机器上 所以对于大多数模块 我无法使用 CPAN 来安装模块 我无权访问 root 帐户 通常 当我想安装模块时 我会
  • 朱莉娅:当我有情节时如何找到最佳拟合曲线/方程?

    朱莉娅 当我有情节时如何找到最佳拟合曲线 方程 我有一个用地图绘制的图 但我需要找到一个适合这个的二次方程 正如评论中所说 情节在这里并不重要 只有数据本身是 您可以使用诸如GLM构建数据的 广义 线性模型 并可能绘制它们或使用它们来预测新
  • 请求的运行时 (python-) 不适用于此堆栈 (heroku-20)

    我在尝试通过 Heroku 部署这个 Flask 应用程序时遇到了困难 我研究了多种方法来解决这个问题 但似乎找不到一种可行的方法 这就是当我推动时我得到的git push heroku master remote gt Building
  • Dev-C++ 输入已跳过

    include
  • .NET 4.0 解决方案中的 NHibernate 1.2

    我有一些基于 NHibernate 1 2 的项目 我想将它们添加到 NET 4 0 解决方案中 但我收到 AmbigeousMatchException 无论这些项目是针对2 0还是4 0框架 如果我将它们添加到 NET 3 5 解决方案
  • 将刻度转换为时间格式 (hh:mm:ss)

    我从网络服务器获取视频长度值作为刻度 我想以 hh mm ss 格式显示它 我怎样才能在 JavaScript 中做到这一点 假设刻度以秒为单位 如果不是 您可以先将其转换为秒 您可以通过查找时间跨度中的整分钟数和小时数 然后获取剩余的秒数
  • 我什么时候应该使用解析器?

    我在正则表达式中遇到了将代码划分为功能组件的问题 它们可能会破裂 也可能需要很长时间才能完成 这段经历提出了一个问题 我什么时候应该使用解析器 当您对以下内容感兴趣时 应该使用解析器文本的词汇或语义意义 当模式可以变化时 当您只是想了解时
  • Java正则表达式正向预测但仅匹配唯一字符?

    我正在尝试将字符串输入与以下条件进行匹配 第一个字符是unique小写英文字母 接下来的字符代表从 1500 到 2020 的当前年份 接下来的字符只能是 10 或 100 或 1000 最后一个字符是 0 到 9 之间的数字 我创建的正则
  • 在多个数据库上使用 ActiveRecord

    我正在编写一个工资系统 它将与现有系统集成 原始系统有一个主数据库 用于处理用户管理和一些全局配置 下面有多个结构相同的数据库 基本上每个数据库都是一个公司的工资数据库 所有这些都与主数据库绑定 因为它属于父数据库公司拥有多家子公司 每个子
  • 在 matplotlib 底图投影上绘制椭圆

    我正在尝试在底图投影上绘制椭圆 要画一个像多边形一样的圆 有tissot用于绘图的函数天梭的指标 http en wikipedia org wiki Tissot 27s indicatrix如下例所示 from mpl toolkits
  • BeautifulSoup XML 仅打印第一行

    我正在使用 BeautifulSoup4 和 lxml 来解析 XML 文件 由于某种原因 当我打印 soup prettify 时 它只打印第一行 from bs4 import BeautifulSoup f open xmlDoc x
  • 将复选框数据插入mysql

    我的问题如下 这是我的 mySQL 表和 HTML 表单 https i stack imgur com g4qp5 jpg 我需要找到一个 PHP 代码来将复选框数据插入到 mySQL 表中 如果选中一个复选框 我想将该特定列填充为 1
  • 如何编写包含引号的字符串文字?

    我想用这个确切的文本创建一个字符串 nuke execute Write1 1 10 1 只需用双引号将其引起来 例如 nuke execute Write1 1 10 1 不起作用 gt gt gt nuke execute Write1
  • 使用自定义 INF 的微控制器的 USB 驱动程序安装问题

    我正在使用 NXP LPC1788 微控制器 并尝试在主机上创建一个驱动程序以通过 USB 与其进行通信 我相信我已经设法让设备正确处理标准 USB 请求 PC 能够正确读取字符串描述符 不过 我在编写示例 USB 驱动程序并为设备安装它时
  • 创建类路径资源中定义的名为“defaultValidator”的 bean 时出错

    尝试在 JBOSS 上部署 Spring Boot 应用程序时出现以下错误 但它在嵌入式 Tomcat 服务器上运行良好 我尝试浏览 Stack Overflow 以查找类似的问题 尚未找到解决方案 任何建议 将不胜感激 谢谢 Error
  • stdClass 或(对象)数组哪个更好地存储相关数据?

    我很长一段时间以来一直使用数组来存储相关字段 如果我想要相关的用户字段 我使用 user array id gt 27 name gt Pepe 但最近 我经常使用对象 我更喜欢使用 user gt id 而不是 user id 我的问题
  • 使用更多派生类型覆盖子类继承的属性

    我想要实现的目标的简化示例如下所示 public class Animal public virtual Teeth teeth get set public class Mouse Animal public override Small