繁体   English   中英

C#中抽象类的构造函数

[英]Constructor of an abstract class in C#

为什么可以在 C# 中为抽象类编写构造函数?
据我所知,我们不能实例化一个抽象类.. 那它有什么用呢?
你不能实例化这个类,对吧?

因为您可能希望在抽象类中实例化数据的标准方式。 这样,您可以让从该类继承的类调用基本构造函数。

public abstract class A{

    private string data;

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

}

public class B : A {

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

}

据我所知,我们无法实例化抽象类

你的错误就在那里。 当然你可以实例化一个抽象类。

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

那里有一个 Animal 的实例。 您通过创建一个派生自抽象类的具体类并实例化它来实例化一个抽象类。 请记住,派生具体类的实例也是其抽象基类的实例。 即使 Animal 是抽象的,Giraffe 的实例也是 Animal 的实例。

鉴于您可以实例化一个抽象类,它需要像任何其他类一样具有构造函数,以确保满足其不变量。

现在,静态类是您实际上无法实例化的类,您会注意到在静态类中创建实例构造函数是不合法的。

这是一种强制执行抽象类的一组不变量的方法。 也就是说,无论子类做什么,您都希望确保基类的某些事情总是正确的......例如:

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

不要将构造函数视为new运算符的对偶。 构造函数的唯一目的是确保您在开始使用之前拥有处于有效状态的对象。 恰好是我们通常通过new运算符调用它。

它可以强制执行抽象类的所有实现或您在抽象类上实现的任何方法所需的一些初始化逻辑(并非抽象类上的所有方法都必须是抽象的,有些可以实现)。

从抽象基类继承的任何类都必须调用基构造函数。

抽象类的要点

  1. 抽象类不能被实例化。
  2. 抽象类可以有构造函数和析构函数。
  3. 抽象类不能是密封类,因为密封修饰符防止类被继承。
  4. 抽象类包含抽象和非抽象成员。
  5. 抽象类成员可以是私有的、受保护的和内部的。
  6. 抽象成员不能有私有访问修饰符。
  7. 抽象成员是隐式虚拟的,必须由非抽象派生类实现。

添加到上述答案和示例。

是的,一个抽象类可以有一个构造函数,即使一个抽象类不能被实例化。 将解释一个抽象类构造函数 c# 代码示例。 但是,也可能会出现下一个问题,好像我们不能实例化(使用 new 构造对象)抽象类,那么抽象类中的构造函数是什么,或者为什么要在抽象类中使用构造函数?

请注意,当我们创建派生类的对象时,会隐式调用抽象基类的构造函数,即使我们无法实例化抽象类。 例如在程序中,如果我们创建一个派生类的对象,那么抽象基类的构造函数也会被调用。

这也是例子之一

例子

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();
    }
}

输出将是

Abstract class constructor
Derived class constructor

抽象类不能直接实例化。 抽象类构造函数从派生类执行。 因此,最好将受保护的访问修饰符与抽象类构造函数一起使用。 公开没有意义

抽象类构造函数也可用于执行与每个子类相关的代码。

这可以防止重复代码。

通常构造函数涉及初始化正在创建的对象的成员。 在继承的概念中,通常继承层次结构中的每个类构造函数都负责实例化自己的成员变量。 这是有道理的,因为必须在定义变量的地方进行实例化。

由于抽象类不是完全抽象的(与接口不同),它是抽象和具体成员的混合体,非抽象的成员需要初始化,这是在抽象类的构造函数中完成的,因此必须有构造函数在抽象类中。 当然,抽象类的构造函数只能从派生类的构造函数中调用。

你是绝对正确的。 我们不能实例化一个抽象类,因为抽象方法没有任何主体,即抽象方法不可能实现。 但是可能有一些场景需要初始化基类的一些变量。 您可以按照@Rodrick 的建议使用base关键字来做到这一点。 在这种情况下,我们需要在抽象类中使用构造函数。

我也想在抽象的表面上做一些闪耀所有的答案几乎涵盖了所有的东西。 还是我的 2 美分

抽象类是普通类,但有一些例外

  1. 您该类的任何客户/消费者都无法创建该类的对象,这绝不意味着它的构造函数永远不会调用。 它的派生类可以选择调用哪个构造函数。(如一些答案所示)
  2. 它可能具有抽象功能。

在可继承的具体类Thing中定义具有公共或内部存储类的构造函数有效地定义了两种方法:

  • 作用于this的方法(我称之为InitializeThing )没有返回值,并且只能从ThingCreateThingInitializeThing方法以及子类的InitializeXXX方法调用。

  • 一个方法(我称之为CreateThing ),它返回构造函数指定类型的对象,本质上表现为:

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

抽象类有效地创建了仅第一种形式的方法。 从概念上讲,上面描述的两个“方法”没有理由需要具有相同的访问说明符。 然而,在实践中,没有办法以不同的方式指定它们的可访问性。 请注意,就实际实现而言,至少在 .NET 中, CreateThing并没有真正实现为可调用方法,而是表示插入到newThing = new Thing(23);处的代码序列。 陈述。

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

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

抽象类型的构造函数只能由派生类型调用。 因为公共构造函数创建类型的实例,而您不能创建抽象类型的实例,所以具有公共构造函数的抽象类型设计不正确。

由于只有派生类可以使用抽象类构造函数,因此如果需要,必须将抽象类构造函数声明为protected

但是,当在抽象类中声明公共构造函数时,VS 编译器不会抱怨(使用默认规则),但是它不允许创建新实例。

您可以在实现所有方法后实例化它。 然后将调用构造函数。

有以下两个重要特性可以防止继承 Abstract 类

  1. 抽象类必须有抽象方法,否则不是抽象类

  2. 抽象类必须由派生类继承,所以如果一个类被其他类继承,而不是用来创建该类的对象

暂无
暂无

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

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