简体   繁体   English

抽象基类中的方法如何从派生类中调用构造函数?

[英]How does a method in an abstract base class call the constructor from a derived class?

As an example, consider the .NET SHA256Managed class. 例如,请考虑.NET SHA256Managed类。

SHA256Managed inherits from the abstract class, SHA256 , which has a method named Create(). SHA256Managed继承自抽象类SHA256 ,该抽象类具有一个名为Create()的方法。 The documentation says Create() instantiates an instance of the default implementation of SHA256. 该文档说Create()实例化SHA256默认实现的实例。

I would have been likely to write something like 我本来可能会写类似

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

Whereas Microsoft's example opts to use: 而Microsoft的示例选择使用:

SHA256 mySHA256 = SHA256Managed.Create();

How does the method like Create() (from a base class), instantiate an instance of a class that derives from it? 像Create()这样的方法(来自基类)如何实例化从该类派生的类的实例?

A function can return an instance of whatever you want it to ;) 函数可以返回您想要的任何实例;)

In this case, an instance of 256Managed is still castable to SHA256 在这种情况下, 256Managed的实例256ManagedSHA256

Something like this is entirely feasible: 这样的事情是完全可行的:

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

Method or property of a class can use any derived classes (or even itself as fields) as much as it wants. 类的方法或属性可以根据需要使用任何派生的类(甚至可以将自身用作字段)。 There is no restrictions in language that a method can only use objects of its own and base class. 在语言上没有限制,即方法只能使用其自身和基类的对象。

The only thing you can't do with abstract class is to new an instance of such class, calling static member of such class that returns whatever valid instance of any non-abstract class/struct is perfectly fine. 您对抽象类不能做的唯一事情就是new一个此类的实例,调用此类的静态成员,该成员返回任何非抽象类/结构的有效实例都很好。

Following valid code shows that it is possible to return either your own or even derived class: 下面的有效代码表明可以返回您自己的甚至派生的类:

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
{
}

Usually, base classes shouldn't have any knowledge its of derived classes - it can however instantiate whatever it wants. 通常,基类不应该对派生类有任何了解-但是它可以实例化任何所需的内容。

In the case of SHA256 however, its Create() method "instantiates the default implementation", which is listed as SHA256Managed. 但是,对于SHA256,其Create()方法“实例化默认实现”,列为SHA256Managed。 Because SHA256Managed doesn't have a create method, it calls its base class' Create() and gets an instance of itself back. 由于SHA256Managed没有创建方法,因此它将调用其基类的Create()并获取其自身的实例。 This can only happen if the base implementation explicitly instantiates SHA256Managed like Alexei + Tom have shown: 仅当基本实现显式实例化SHA256Managed(如Alexei + Tom所示)时,才会发生这种情况:

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

In the SHA256 class, the Create method is a static method that returns 'an instance of the default implementation of System.Security.Cryptography.SHA256' (according to the method documentation). SHA256类中, Create方法是一个静态方法,该方法返回“ System.Security.Cryptography.SHA256默认实现的实例”(根据方法文档)。 This default implementation is SHA256Managed - a non-abstract child class of SHA256 . 此默认实现为SHA256Managed - SHA256的非抽象子类。

The SHA256 and SHA256Managed classes are defined in the same assembly, so SHA256Managed is available to SHA256.Create as a valid class. SHA256SHA256Managed类在同一程序SHA256Managed定义,因此SHA256Managed可用于SHA256.Create作为有效类。

Here's an example of an abstract base class with a static Create method that creates an instance of a non-abstract derived class: 这是一个带有静态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.
    }
}

Effectively what happens is the compiler builds a list of the classes and their members for your entire assembly before it compiles the code for those members. 实际上,发生的事情是,编译器在编译这些成员的代码之前,会为您的整个程序集构建类及其成员的列表。 So by the time the A.Create method is being compiled the compiler already knows about the existence and structure of class B . 因此,在编译A.Create方法时,编译器已经知道类B的存在和结构。

That's also why it is OK to put properties and methods in a class after the first point where you refer to them, like so: 这就是为什么可以将属性和方法放在引用它们的第一点之后的类中的原因,如下所示:

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

    int counter;
}

The compiler already knows the entire structure of class C before it compiles the code for some_method so it can compile the statement ++counter; 在编译some_method的代码之前,编译器已经知道C类的整个结构,因此它可以编译++counter;语句++counter; without errors. 没有错误。

if i am not mistaken you are thinking of SHA256Managed.Create() is calling the Create() method of the SHA256 the base class. 如果我没记错的话,您会想到SHA256Managed.Create()正在调用SHA256Create()方法作为基类。

Create() method is a static method which is not overrideable, it is implemented on SHA256Managed class with new keyword. Create()方法是不可重写的静态方法,它是在SHA256Managed类上使用new关键字实现的。 se here for more info 在这里获取更多信息

EDIT 编辑

So, after digging deeper (using ILSPY) i found that Create() method of SHA256 isn't that simple, it is call another class CryptoConfig.CreateFromName . 因此,在深入研究(使用ILSPY)之后,我发现SHA256 Create()方法并不是那么简单,它被称为另一个类CryptoConfig.CreateFromName just a guess the information about SHA256Managed (derived class) is reside in some configuration mechanism. 只是有关SHA256Managed (派生类)的信息位于某种配置机制中。

@ 280Z28 : thak you for your correction @ 280Z28 :感谢您的指正

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM