【问题标题】:How does a method in an abstract base class call the constructor from a derived class?抽象基类中的方法如何从派生类调用构造函数?
【发布时间】:2013-06-07 00:17:02
【问题描述】:

.NET SHA256Managed 类为例。

SHA256Managed 继承自抽象类SHA256,它有一个名为 Create() 的方法。文档说 Create() 实例化了 SHA256 的默认实现的一个实例。

我可能会写类似的东西

using (SHA256Managed Sha256Managed = new SHA256Managed())
{
  // code
}

而微软的示例选择使用:

SHA256 mySHA256 = SHA256Managed.Create();

Create() 之类的方法(来自基类)如何实例化派生自它的类的实例?

【问题讨论】:

  • 我猜它会以正常方式实例化它。也许在其他语言中有所不同,但在 C# 中,类之间的“循环”引用不是问题。
  • 您在 Microsoft 的示例代码中看到的是对接口编程的示例。见stackoverflow.com/questions/383947/…

标签: c# .net


【解决方案1】:

函数可以返回任何你想要的实例;)

在这种情况下,256Managed 的实例仍然可以转换为 SHA256

这样的事情是完全可行的:

public class SHA256Managed 
{
   public static SHA256 Create() 
   {
       return new SHA256Managed();
   }
}

【讨论】:

  • 我以为你不允许实例化像 SHA256 这样的抽象类?
【解决方案2】:

SHA256 类中,Create 方法是一个静态方法,它返回“System.Security.Cryptography.SHA256 的默认实现的实例”(根据方法文档)。此默认实现是SHA256Managed - SHA256 的非抽象子类。

SHA256SHA256Managed 类在同一个程序集中定义,因此 SHA256Managed 可作为有效类供 SHA256.Create 使用。

下面是一个抽象基类的例子,它带有一个静态的Create 方法,它创建了一个非抽象派生类的实例:

public abstract class A
{
    public static A Create()
    {
        return new B();
    }

    public abstract void DoSomething();
}

public class B : A
{
    public override void DoSomething()
    {
        // do nothing.
    }
}

实际上,编译器会在为这些成员编译代码之前为整个程序集构建一个类及其成员的列表。因此,在编译 A.Create 方法时,编译器已经知道类 B 的存在和结构。

这也是为什么可以将属性和方法放在类中你引用它们的第一个点之后,就像这样:

class C
{
    void some_method()
    {
        ++counter;
    }

    int counter;
}

编译器在编译 some_method 的代码之前已经知道类 C 的整个结构,因此它可以编译语句 ++counter; 而不会出错。

【讨论】:

    【解决方案3】:

    类的方法或属性可以根据需要使用任何派生类(甚至本身作为字段)。语言没有限制,方法只能使用自己的对象和基类。

    你不能对抽象类做的唯一事情是 new 此类的一个实例,调用此类的静态成员返回任何非抽象类/结构的任何有效实例都很好。

    以下有效代码表明可以返回您自己的甚至派生类:

    class Base 
    {
      public Derived Property1 {get;set;}
      public Base Property2 {get;set;}      
    
      public static Base Create()
      {
        return new Derived();
      }
    
      public static Derived Create2()
      {
        return new Derived();
      }
    }
    
    class Derived : Base
    {
    }
    

    【讨论】:

      【解决方案4】:

      通常,基类不应该对派生类有任何了解 - 但是它可以实例化任何它想要的东西。

      但是,在 SHA256 的情况下,它的 Create() 方法“实例化了默认实现”,它被列为 SHA256Managed。因为 SHA256Managed 没有 create 方法,所以它调用它的基类 Create() 并取回它自己的一个实例。这只有在基础实现显式实例化 SHA256Managed 时才会发生,就像 Alexei + Tom 所示:

              public static SHA256 Create()
              {
                  return new SHA256Managed();
              }
      

      【讨论】:

      • 感谢所有回复的人。这个答案连接了所有的点。查看源代码(直到现在才知道它可用),微软确实将他们的 SHA256 基类与他们的 SHA256Managed 类紧密耦合(通过常量字符串)。他们还使用 new 来隐藏继承层次结构中较高的 Create() 定义。我希望我可以分配一个以上的正确答案。感谢大家抽出宝贵时间回复有用的信息!
      【解决方案5】:

      如果我没记错的话,您认为SHA256Managed.Create() 正在调用基类SHA256Create() 方法。

      Create() 方法是一个不可重写的静态方法,它是在 SHA256Managed 类上实现的,带有 new 关键字。 se here for more info

      编辑

      所以,在深入挖掘(使用 ILSPY)之后,我发现 SHA256Create() 方法并不是那么简单,它是调用另一个类 CryptoConfig.CreateFromName。只是猜测关于SHA256Managed(派生类)的信息存在于某种配置机制中。

      @280Z28:谢谢指正

      【讨论】:

      • -1: SHA256Managed 没有实现静态的Create 方法。 Create 方法是 SHA256 类的一部分。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-03-05
      • 1970-01-01
      • 1970-01-01
      • 2010-09-21
      • 1970-01-01
      • 2016-07-19
      • 1970-01-01
      相关资源
      最近更新 更多