c#中抽象类的构造函数

本文关键字:构造函数 抽象类 | 更新日期: 2023-09-27 17:49:45

为什么可以在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的实例,即使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操作符调用它。

加上以上的答案和例子

是的,抽象类可以有构造函数,即使抽象类不能被实例化。将解释一个抽象类构造函数的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

抽象类要点

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

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

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

你完全正确。我们不能实例化抽象类,因为抽象方法没有任何主体,也就是说,抽象方法不可能实现。但是在某些情况下,您可能希望初始化基类的一些变量。您可以通过使用@Rodrick建议的base关键字来做到这一点。在这种情况下,我们需要在抽象类中使用构造函数。

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

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

使用抽象类是标准化代码的一种方式。它也可以被看作是为其他类准备模板或蓝图的一种方式。想想现在市面上不同类型的汽车:SUV、轿车、双门轿跑车、掀背车等等。它们都有相同的基本蓝图,例如它们都有转向、刹车、离合器等。但仍然有许多特点和功能的不同,在所有的汽车。因此,我们可以把它看作是声明了一个抽象的car类,其中包括所有汽车需要实现的标准化方法/功能,但除此之外,不同类型的汽车也可以添加自己的特性/功能。现在回到你的问题,并把它与上面给出的例子联系起来。看看我们是否必须制造一辆汽车,显然它将是上面提到的那种(SUV,Sedan.....),也就是说,为了创建一个抽象类的实例,我们需要继承它。这就是为什么它被称为"必须继承类"。如果构造函数也包含在抽象类中,则意味着所有派生类也需要使用构造函数。如果我们运行这样的代码:-

public abstract class AbstractClass
{
    public AbstractClass()
    {
        Console.WriteLine("Abstract class constructor");
    }
}
public class derived : AbstractClass 
{ 
    public derived()
    {
        Console.WriteLine("Derived class constructor");
    }
}
class Program
{
    public static void Main(string[] args)
    {
        derived d= new derived();
        Console.ReadLine();
    }
}

那么输出将是:-

    Abstract class constructor
    Derived class constructor

清楚地表明构造函数也可以在抽象类中使用。

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

我也想在抽象的表面上发光所有的答案几乎涵盖了所有的事情。仍然是我的2美分

抽象类是除少数例外的普通类

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

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

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

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

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

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

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

抽象类型上的

构造函数只能由派生类型调用。由于公共构造函数创建类型的实例,而不能创建抽象类型的实例,因此具有公共构造函数的抽象类型设计错误。

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

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

有以下两个重要的特性阻止继承抽象类

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

  2. 抽象类必须被派生类继承,所以如果一个类被其他类继承,那就用什么来创建这个类的对象