【问题标题】:Create an instance of a derived class using static method of base class [closed]使用基类的静态方法创建派生类的实例[关闭]
【发布时间】:2015-06-05 19:18:47
【问题描述】:

关于以下模型,我该如何编写方法Make来实现 使用目的?

注意: 我不想在每个派生类中重复Make 方法。

用法:

Derived instance = Drived.Make();
AnotherDerived instance = AnotherDrived.Make();
ThirdDerived instance = ThirdDrived.Make();

型号:

class Base
{
   public static Base Make()
   {
       // What to write here?
   }
}

class Derived : Base
{
}

class AnotherDerived : Base
{
}

class ThirdDerived : Base
{
}

【问题讨论】:

  • ??? =return new Derived();。请澄清你的问题。你的意图是什么?
  • @usr 请让我在否决之前完成问题?
  • 也许在发布问题之前,您应该完成它(尽管我没有投反对票)。
  • 我没有投反对票。我试图找出你想要达到的目标,以便我可以给你你需要的东西。问题的第一个版本没有明显的答案。
  • 汉斯,我知道有十几种方法可以实现您的字面意思。在不知道你的目标是什么的情况下,我应该如何选择?不要放弃。回答人们的问题。提出这些问题是有原因的(这对您来说可能并不明显)。

标签: c# oop inheritance static-methods


【解决方案1】:

你可以这样写:

class Derived : Base
{
   public static Derived Make()
   {
       ???
   }
}

Base 有一个Make 方法无关紧要,它们都是静态的,因此彼此没有关系。

【讨论】:

  • 我不想在每个派生类中重复 Make
  • @Hans 为什么需要 Make?使用new
  • 静态类不是继承的,所以你必须在每个类中重复它。你只是想建一个工厂吗? en.wikipedia.org/wiki/Factory_method_pattern.
  • @shf301 这不是静态类。 make 是一个静态方法
  • static 方法在某种意义上是继承的。您可以将它们称为Derived.Make()(或从Derived 内部键入Make()),但编译器只是将语法转换为Base.Make() 调用。由于这种继承,您的方法隐藏原始方法。您需要new 修饰符,例如public new static Derived Make()。但是这种方法有一点味道(new 修饰符的所有用法)。
【解决方案2】:

尽管人们给出了所有好的解决方案,但我得出的结论是这是不可能的。我的问题的根源是误解了静态方法如何在派生类上工作。我刚刚发现Derived.Make() 立即编译为Base.Make(),因此Base 永远不知道Make 被调用的类型。 Derived.Make() 只是一个捷径。

【讨论】:

  • 你去。很高兴你的问题得到了解决(有点)。所有现有的答案都是现在已经过时的猜测答案。这就是为什么我在回答之前询问详细信息。我希望你明白我的出发点。
  • 你是绝对正确的。如果您对 Base 作为泛型类型 ("curiously recurring" pattern) 感到满意,则可以使用一个技巧。请参阅 bcwhims 的回答。
【解决方案3】:

静态方法不会被继承。从语法上看,它们确实是,但是在编译时,会直接调用基类方法。您必须在基类中有某种方式来指示您要创建的类型。我认为这可以通过在方法上使用泛型(如另一个答案中所建议的那样)或在类本身上来完成:

class Base<T> where T : new()
{
    public static T Make()
    {
        return new T();
    }
}

class Derived : Base<Derived>
{
}

class AnotherDerived : Base<AnotherDerived>
{
}

class ThirdDerived : Base<ThirdDerived>
{
}

【讨论】:

  • 我也在考虑这个解决方案。使用此解决方案,var instance = ThirdDerived.Make(); 将是一个强类型 ThirdDerived 实例。这不是因为static 方法在派生类中被“修改”了。语法ThirdDerived.Make() 被编译器视为Base&lt;ThirdDerived&gt;.Make()(因为ThirdDerived 的基类是Base&lt;ThirdDerived&gt;)。
  • T 可能是 Base,至少在这一点上最新的 C# 看起来是这样?然后,您可以调用 Derived.Make,只要 Derived:Base (即所有派生类都必须是自引用的,基本静态方法才能工作)。
【解决方案4】:

如果只有一种方法,您可以使用通用方法:

class Base
{
   public static T Make<T>() where T : Base
   {
       if (typeof(T) == typeof(Derived)) 
       {
            return (T)(object)new Derived();
       }
       // obviously more cases in here. just for illustration.
       else
       {
            return null;
       }
   }
}

那么你必须把它称为

Derived d = Base.Make<Derived>();

没有选项可以在基类中编写一个方法并让Derived.MakeAnotherDerived.Make 执行其他操作(此外,还可以像您的示例一样返回不同的类型),除非您考虑使用代码生成选项。这些不是引擎盖下的不同方法。它们充当Base.Make 的别名,除非您在每个派生类中定义新方法。

【讨论】:

  • 如果我查看代码库并看到 Base.Make&lt;Derived&gt;,我会喜欢 O_o。
  • @YuvalItzchakov 也不是我最喜欢的模式,但更是如此,因为我认为它是对泛型的滥用。 Make&lt;T&gt; 不能真正制作任何类型 T。它只能制作我硬编码的几种类型,然后需要记录。如果它可以限制谁从 Base 继承,那么我为什么不在每个派生类中放置一个方法,因为它们在我的控制之下。
  • @mike.z 我支持你。从 OP 的问题来看,我仍然不清楚制作这种 Make 方法的意图。他真正想要达到的目标是什么。
  • 您不必限制某些类型。您可以将 where 更改为 where T : Base, new() 并将方法更改为 return new T();
  • @bcwhims 如果我们这样做,当我们有一个非常好的东西来创造东西时,为什么我们还需要 Make:new?我们也可以使用 Activator.CreateInstance 与构造函数的一些约定,同样它需要一些文档。
【解决方案5】:

您可以为每个派生类定义转换构造函数并像这样使用make:(Derived)Derived.Make();

【讨论】:

  • 在每个派生类中重复 Make 不是一种选择
  • Make 只能在基类中,您只能在每个派生类中定义转换构造函数。
猜你喜欢
  • 2014-04-27
  • 2011-02-24
  • 2014-09-29
  • 2012-05-24
  • 2023-02-22
  • 2015-04-08
  • 2019-07-25
  • 2013-09-02
  • 2016-07-06
相关资源
最近更新 更多