C#中抽象类的构造函数

时间:2011-04-08 23:32:11

标签: c# constructor abstract-class

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

13 个答案:

答案 0 :(得分:258)

  

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

那里有你的错误。 当然,您可以实例化一个抽象类。

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

那里有一个动物实例。您通过创建一个从它派生的具体类来实例化一个抽象类,并实例化它。请记住,派生具体类的实例也是其抽象基类的实例。 即使动物是抽象的,长颈鹿的实例也是动物的实例。

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

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

答案 1 :(得分:229)

因为可能有一种标准方法要在抽象类中实例化数据。这样,您可以从该类继承的类调用基础构造函数。

public abstract class A{

    private string data;

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

}

public class B : A {

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

}

答案 2 :(得分:20)

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

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运算符调用它。

答案 3 :(得分:5)

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

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

答案 4 :(得分:1)

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

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

答案 5 :(得分:0)

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

答案 6 :(得分:0)

  

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

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

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

答案 7 :(得分:0)

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

  • InitializeThing采取行动的方法(我称之为this)没有返回值,只能从Thing {{1}调用}}和CreateThing方法,以及子类'InitializeThing方法。

  • 一种方法(我称之为InitializeXXX),它返回构造函数指定类型的对象,并且基本上表现为:

    CreateThing

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

答案 8 :(得分:0)

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

答案 9 :(得分:0)

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

  

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

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

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

答案 10 :(得分:0)

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

答案 11 :(得分:0)

抽象类的要点

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

答案 12 :(得分:-1)

以下两个重要功能阻止继承Abstract class

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

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