简体   繁体   English

C#中抽象类的构造函数

[英]Constructor of an abstract class in C#

Why is it possible to write constructor for an abstract class in C#?为什么可以在 C# 中为抽象类编写构造函数?
As far as I know we can't instantiate an abstract class.. so what is it for?据我所知,我们不能实例化一个抽象类.. 那它有什么用呢?
You can't instantiate the class, right?你不能实例化这个类,对吧?

Because there might be a standard way you want to instantiate data in the abstract class.因为您可能希望在抽象类中实例化数据的标准方式。 That way you can have classes that inherit from that class call the base constructor.这样,您可以让从该类继承的类调用基本构造函数。

public abstract class A{

    private string data;

    protected A(string myString){
      data = myString;
    }

}

public class B : A {

     B(string myString) : base(myString){}

}

Far as I know we can't instantiate an abstract class据我所知,我们无法实例化抽象类

There's your error right there.你的错误就在那里。 Of course you can instantiate an abstract class.当然你可以实例化一个抽象类。

abstract class Animal {}
class Giraffe : Animal {}
...
Animal animal = new Giraffe();

There's an instance of Animal right there.那里有一个 Animal 的实例。 You instantiate an abstract class by making a concrete class derived from it, and instantiating that.您通过创建一个派生自抽象类的具体类并实例化它来实例化一个抽象类。 Remember, an instance of a derived concrete class is also an instance of its abstract base class.请记住,派生具体类的实例也是其抽象基类的实例。 An instance of Giraffe is also an instance of Animal even if Animal is abstract.即使 Animal 是抽象的,Giraffe 的实例也是 Animal 的实例。

Given that you can instantiate an abstract class, it needs to have a constructor like any other class, to ensure that its invariants are met.鉴于您可以实例化一个抽象类,它需要像任何其他类一样具有构造函数,以确保满足其不变量。

Now, a static class is a class you actually cannot instantiate, and you'll notice that it is not legal to make an instance constructor in a static class.现在,静态类是您实际上无法实例化的类,您会注意到在静态类中创建实例构造函数是不合法的。

It's a way to enforce a set of invariants of the abstract class.这是一种强制执行抽象类的一组不变量的方法。 That is, no matter what the subclass does, you want to make sure some things are always true of the base class... example:也就是说,无论子类做什么,您都希望确保基类的某些事情总是正确的......例如:

abstract class Foo
{
    public DateTime TimeCreated {get; private set;}

    protected Foo()
    {
         this.TimeCreated = DateTime.Now;
    }
}

abstract class Bar : Foo
{
    public Bar() : base() //Bar's constructor's must call Foo's parameterless constructor.
    { }
}

Don't think of a constructor as the dual of the new operator.不要将构造函数视为new运算符的对偶。 The constructor's only purpose is to ensure that you have an object in a valid state before you start using it.构造函数的唯一目的是确保您在开始使用之前拥有处于有效状态的对象。 It just happens to be that we usually call it through a new operator.恰好是我们通常通过new运算符调用它。

It's there to enforce some initialization logic required by all implementations of your abstract class, or any methods you have implemented on your abstract class (not all the methods on your abstract class have to be abstract, some can be implemented).它可以强制执行抽象类的所有实现或您在抽象类上实现的任何方法所需的一些初始化逻辑(并非抽象类上的所有方法都必须是抽象的,有些可以实现)。

Any class which inherits from your abstract base class will be obliged to call the base constructor.从抽象基类继承的任何类都必须调用基构造函数。

Key Points About Abstract Class抽象类的要点

  1. An abstract class cannot be instantiated.抽象类不能被实例化。
  2. An abstract class can have constructor and destructor.抽象类可以有构造函数和析构函数。
  3. An abstract class cannot be a sealed class because the sealed modifier prevents a class from being inherited.抽象类不能是密封类,因为密封修饰符防止类被继承。
  4. An abstract class contains abstract as well as non-abstract members.抽象类包含抽象和非抽象成员。
  5. An abstract class members can be private, protected and internal.抽象类成员可以是私有的、受保护的和内部的。
  6. Abstract members cannot have a private access modifier.抽象成员不能有私有访问修饰符。
  7. Abstract members are implicitly virtual and must be implemented by a non-abstract derived class.抽象成员是隐式虚拟的,必须由非抽象派生类实现。

Adding to the above answers and examples.添加到上述答案和示例。

Yes, an abstract class can have a constructor, even though an abstract class cannot be instantiated.是的,一个抽象类可以有一个构造函数,即使一个抽象类不能被实例化。 An abstract class constructor c# code example will be explained.将解释一个抽象类构造函数 c# 代码示例。 But, the next question can also be arises, as if we cannot instantiate (construct an object using new) an abstract class, then what for a constructor is in an abstract class or why should we use a constructor in abstract class?但是,也可能会出现下一个问题,好像我们不能实例化(使用 new 构造对象)抽象类,那么抽象类中的构造函数是什么,或者为什么要在抽象类中使用构造函数?

Note that when we create an object of a derived class then the constructor of the abstract base class is implicitly called, even though we cannot instantiate an abstract class.请注意,当我们创建派生类的对象时,会隐式调用抽象基类的构造函数,即使我们无法实例化抽象类。 For example in the program, if we create an object of a derived class then the abstract base class constructor will also be called.例如在程序中,如果我们创建一个派生类的对象,那么抽象基类的构造函数也会被调用。

This is also one of the example这也是例子之一

Examples例子

abstract class A
{
    protected A() {Console.WriteLine("Abstract class constructor"); }
}
//Derived class
class B : A
{
   public B() {Console.WriteLine("Derived class constructor"); }
}

class Program
{
    static void Main(string[] args)
    {
        B obj = new B();
    }
}

Output will be输出将是

Abstract class constructor
Derived class constructor

Abstract classes can't be directly instantiated.抽象类不能直接实例化。 The abstract class constructor gets executed from a derived class.抽象类构造函数从派生类执行。 So, it is a good practice to use a protected access modifier with an abstract class constructor.因此,最好将受保护的访问修饰符与抽象类构造函数一起使用。 Making it public doesn't make sense公开没有意义

An abstract class constructor can also be used to execute code that is relevant for every child class.抽象类构造函数也可用于执行与每个子类相关的代码。

This prevents duplicate code.这可以防止重复代码。

Normally constructors involve initializing the members of an object being created.通常构造函数涉及初始化正在创建的对象的成员。 In concept of inheritance, typically each class constructor in the inheritance hierarchy, is responsible for instantiating its own member variables.在继承的概念中,通常继承层次结构中的每个类构造函数都负责实例化自己的成员变量。 This makes sense because instantiation has to be done where the variables are defined.这是有道理的,因为必须在定义变量的地方进行实例化。

Since an abstract class is not completely abstract (unlike interfaces), it is mix of both abstract and concrete members, and the members which are not abstract are needed to be initialized, which is done in abstract class's constructors, it is necessary to have constructors in the abstract class.由于抽象类不是完全抽象的(与接口不同),它是抽象和具体成员的混合体,非抽象的成员需要初始化,这是在抽象类的构造函数中完成的,因此必须有构造函数在抽象类中。 Off course the abstract class's constructors can only be called from the constructors of derived class.当然,抽象类的构造函数只能从派生类的构造函数中调用。

You are absolutely correct.你是绝对正确的。 We cannot instantiate an abstract class because abstract methods don't have any body ie implementation is not possible for abstract methods.我们不能实例化一个抽象类,因为抽象方法没有任何主体,即抽象方法不可能实现。 But there may be some scenarios where you want to initialize some variables of base class.但是可能有一些场景需要初始化基类的一些变量。 You can do that by using base keyword as suggested by @Rodrick.您可以按照@Rodrick 的建议使用base关键字来做到这一点。 In such cases, we need to use constructors in our abstract class.在这种情况下,我们需要在抽象类中使用构造函数。

I too want to make some shine on abstract surface All answer has covered almost all the things.我也想在抽象的表面上做一些闪耀所有的答案几乎涵盖了所有的东西。 Still my 2 cents还是我的 2 美分

abstract classes are normal classes with A few exceptions抽象类是普通类,但有一些例外

  1. You any client/Consumer of that class can't create object of that class, It never means that It's constructor will never call.您该类的任何客户/消费者都无法创建该类的对象,这绝不意味着它的构造函数永远不会调用。 Its derived class can choose which constructor to call.(as depicted in some answer)它的派生类可以选择调用哪个构造函数。(如一些答案所示)
  2. It may has abstract function.它可能具有抽象功能。

Defining a constructor with public or internal storage class in an inheritable concrete class Thing effectively defines two methods:在可继承的具体类Thing中定义具有公共或内部存储类的构造函数有效地定义了两种方法:

  • A method (which I'll call InitializeThing ) which acts upon this , has no return value, and can only be called from Thing 's CreateThing and InitializeThing methods, and subclasses' InitializeXXX methods.作用于this的方法(我称之为InitializeThing )没有返回值,并且只能从ThingCreateThingInitializeThing方法以及子类的InitializeXXX方法调用。

  • A method (which I'll call CreateThing ) which returns an object of the constructor's designated type, and essentially behaves as:一个方法(我称之为CreateThing ),它返回构造函数指定类型的对象,本质上表现为:

     Thing CreateThing(int whatever) { Thing result = AllocateObject<Thing>(); Thing.initializeThing(whatever); }

Abstract classes effectively create methods of only the first form.抽象类有效地创建了仅第一种形式的方法。 Conceptually, there's no reason why the two "methods" described above should need to have the same access specifiers;从概念上讲,上面描述的两个“方法”没有理由需要具有相同的访问说明符。 in practice, however, there's no way to specify their accessibility differently.然而,在实践中,没有办法以不同的方式指定它们的可访问性。 Note that in terms of actual implementation, at least in .NET, CreateThing isn't really implemented as a callable method, but instead represents a code sequence which gets inserted at a newThing = new Thing(23);请注意,就实际实现而言,至少在 .NET 中, CreateThing并没有真正实现为可调用方法,而是表示插入到newThing = new Thing(23);处的代码序列。 statement.陈述。

抽象类可以有需要初始化的成员变量,因此可以在抽象类构造函数中初始化它们,并在初始化派生类对象时调用该构造函数。

From https://msdn.microsoft.com/en-us/library/ms182126.aspx来自https://msdn.microsoft.com/en-us/library/ms182126.aspx

Constructors on abstract types can be called only by derived types.抽象类型的构造函数只能由派生类型调用。 Because public constructors create instances of a type, and you cannot create instances of an abstract type, an abstract type that has a public constructor is incorrectly designed.因为公共构造函数创建类型的实例,而您不能创建抽象类型的实例,所以具有公共构造函数的抽象类型设计不正确。

Since only derived classes can use an abstract class constructor then an abstract class constructor, if needed, must be declared as protected .由于只有派生类可以使用抽象类构造函数,因此如果需要,必须将抽象类构造函数声明为protected

However, that said VS compiler will not complain (with default rules) when declaring public constructors in abstract classes however it will not allow creating a new instance.但是,当在抽象类中声明公共构造函数时,VS 编译器不会抱怨(使用默认规则),但是它不允许创建新实例。

You can instantiate it after you implemented all the methods.您可以在实现所有方法后实例化它。 Then the constructor will be called.然后将调用构造函数。

There are two following important features that prevent to inherit Abstract class有以下两个重要特性可以防止继承 Abstract 类

  1. Abstract class must have an abstract method otherwise it is not a abstract class抽象类必须有抽象方法,否则不是抽象类

  2. Abstract class must be inherited by derived class,So if a class inherited by other class than what is use of to create object of that class抽象类必须由派生类继承,所以如果一个类被其他类继承,而不是用来创建该类的对象

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

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