【问题标题】:Can I instance a class that inherits the values of an instance of a superclass?我可以实例化一个继承超类实例值的类吗?
【发布时间】:2011-08-17 17:08:45
【问题描述】:

我正在使用 C#,但我认为这是一个非常通用的 OO 问题。假设我有一个名为 Animal 的类,它具有 LegCount、EyeCount、HasFur、EatsMeat 等属性。

假设我有一个 Animal 的实例 a。假设a 将 LegCount 设置为 4,EyeCount 设置为 2。

现在,我想创建一个 Dog 类型的实例 d,它继承自 Animal。我想用a 的所有值初始化d。我意识到我可以创建一个构造函数或其他一些方法来获取一个 Animal 并吐出一个新的 Dog 并复制所有值,但我希望有一些面向对象的原则/技巧让我有所了解。

我想做的,用简单的英语,是:

创建 Dog 的新实例 d,所有起始值均来自 a。关键是“全部”,而不是单独指定每个属性。

当你设计一个继承自其他类的类时,你不需要列出它继承的所有成员。它只是继承了所有这些。所以我想知道我是否可以在实际实例上“继承值”。

【问题讨论】:

  • 就纯粹的 OOP 而言,我认为“[创建] 一个构造函数或其他一些其他方法会采用 Animal 并吐出一个包含所有复制值的新 Dog”实际上 -是——诀窍。您可以定义 Dog(Animal a) 形式的构造函数,而不是 Dog(int LegCount, int EyeCount, ...)。您可能仍然需要自己进行一对一的分配,但从 OO 的角度来看,这是“诀窍”,AFAIK
  • 似乎我应该能够说“这是一只动物。给我你能管理的最全面的狗。”带有一两个关键字 =)
  • 我同意。顺便说一句,io 在一定程度上可以做到这一点。您实际上可以从实例继承。 iolanguage.com(我知道这对 C# 没有帮助,但 io 很有趣)

标签: c# oop


【解决方案1】:

您想要的功能称为“原型继承”或“prototype-oriented programming”。 C# 不支持此功能,因此您不走运。

如果您的架构从根本上需要此功能,您可以考虑使用支持原型继承的语言。 JavaScript 是最常用的原型继承语言。

如果您不小心,原型继承可能会非常棘手。如果您对这个主题感兴趣,请参阅我关于在 JScript 中使用原型继承可能遇到的一些奇怪情况的文章:

http://blogs.msdn.com/b/ericlippert/archive/2003/11/06/53352.aspx

【讨论】:

  • 我认为我根本不需要这个功能。我还在学习 C# 和 OO,并且想确保在我做其他事情之前,我没有跳过一些内置方式,导致未来的开发人员可能会查看我的代码并思考“但他为什么不只是...”。 +1 为我提供了我所想的名称。现在我可以阅读所有相关信息。我也会看看你的博文。谢谢!
【解决方案2】:

你不能用一些 C# 语言结构来做你要求的事情,你必须手动编写映射或委托代码。或者,查看AutoMapper

【讨论】:

  • 在阅读完这里的所有内容后,听起来只是复制一些属性是正确的方法,但我很欣赏这个答案,因为它可以帮助我解决我遇到的另一个问题!在某些对象的序列化过程中,我遇到了这些循环引用警告,这将帮助我管理简化的 DTO!
【解决方案3】:

您可以尝试使用装饰器模式的不同方法吗?用于扩展功能的子类化的替代方法。然后保存 Animal 类实例中的所有值

http://www.dofactory.com/Patterns/PatternDecorator.aspx

【讨论】:

  • +1 我一直在思考这些问题,但忘记了装饰器模式。对于这种情况,我认为它可以很好地使用 Quadruped、Carnivore 等包装器
  • 你需要某种复制结构,否则你会修改装饰时使用的物品,如果他仍在使用 Animal 实例,可能会导致问题。
  • @John,原始对象不能保存为“内部”对象,那么扩展是装饰器合同的一部分吗?
  • 是的,它可以保留,但由于 Animal 'a' 是一个参考,如果他想在其他地方继续使用 'a' 可能会导致问题。修改“d.LegCount”也会修改“a.LegCount”。如果 OP 不再需要“a”,那么您的答案是正确的。
  • 是的,这就是装饰器模式的全部意义所在。扩展功能,而不是修改现有的
【解决方案4】:
public class Animal
{
    public Animal(Animal otherAnimal)
    {
        if (otherAnimal == null)
            throw new ArgumentNullException("otherAnimal");

        foreach (System.Reflection.PropertyInfo property 
            in typeof(Animal).GetProperties())
        {
            property.SetValue(this, property.GetValue(otherAnimal, null), null);
        }
    }
}

然后从你的 Dog(Animal otherAnimal) 构造函数中调用这个 Animal 构造函数

但是您仍然应该再考虑一下您的类的设计,并使 Animal 成为一个抽象类。因为你认为动物类的实例是什么......

【讨论】:

    猜你喜欢
    • 2012-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-19
    • 2015-09-10
    • 1970-01-01
    • 2020-11-21
    相关资源
    最近更新 更多