【问题标题】:Why can't an object of abstract class be created?为什么不能创建抽象类的对象?
【发布时间】:2010-04-23 16:30:16
【问题描述】:

这是我脑海中的一个场景,我用谷歌搜索了很多,但得到了类似的答案

“抽象类没有实现方法所以我们不能创建对象” “‘抽象’这个词指示编译器不要创建类的对象”

但是在一个简单的类中,我们拥有所有的虚方法,能够创建一个对象???

另外,我们可以定义不同的访问抽象类构造函数,如私有、受保护或公共。

我的搜索终止于这个问题:

为什么我们不能创建抽象类的对象?

【问题讨论】:

    标签: language-agnostic oop


    【解决方案1】:

    abstract 类型在很大程度上定义为一种无法创建的类型。您可以创建它的子类型,但不能创建该类型本身。 CLI 不允许您这样做。

    abstract 类有一个 protected 构造函数(默认情况下)允许派生类型对其进行初始化。

    例如,基本类型Stream 是抽象的。如果没有派生类型数据会去哪里?当您调用abstract 方法时会发生什么?调用的方法不会有实际的实现。

    【讨论】:

    • 这是真正的交易,抽象方法:D
    • @Mac 感谢您解释这些话但问题仍然存在:为什么我们不能创建类的对象? Abstract 类的构造函数的默认修饰符是 Protected 但我们可以定义一个公共构造函数然后公共构造函数的用途是什么。
    • @Gaurav - 简而言之,因为它就是这样定义的。对于abstract 方法,这是为了提供理智,但即使没有它也没有任何意义。如果您希望能够创建实例 - **不要标记它abstract **
    • @Mac 再次感谢您的精彩回复。实际上,在这种情况下我会使用一个简单的类。但我仍然想知道,如果微软允许我们为抽象类创建一个公共构造函数,那么我认为这背后有一些原因。否则为什么我们可以为抽象类声明公共构造函数,因为抽象类已经有受保护的构造函数。我在这里有点困惑,如果我们可以为抽象类创建私有、受保护或公共构造函数,那么为什么我们不能创建对象?
    • 抽象类是子类必须实现的受保护和/或公共方法的定义。它是 OOP 的一个基本方面。您不能在 C# 中创建具有抽象方法的类的实例,因为没有定义抽象方法应该做什么。其他一些语言,如 Delphi 7,将允许在实例尝试调用抽象方法时创建具有可预测结果的抽象类实例。
    【解决方案2】:

    因为它是抽象的,而对象是具体的。抽象类有点像模板,或空/部分空的结构,您必须先扩展它并在其上构建,然后才能使用它。

    以“动物”抽象类为例。没有所谓的“纯”动物——有特定类型的动物。所以你可以实例化 Dog、Cat 和 Turtle,但你不应该实例化普通的 Animal——这只是一个基本模板。并且所有动物都共享某些功能,例如“makeSound()",,但不能在基础动物级别上定义。因此,如果您可以创建一个动物对象并调用makeSound(),,该对象将如何知道哪个声音制作?

    【讨论】:

      【解决方案3】:

      它旨在用作基类。

      http://msdn.microsoft.com/en-us/library/sf985hc5(VS.71).aspx

      abstract 修饰符可以与 类、方法、属性、 索引器和事件。

      在类中使用抽象修饰符 声明表明一个类 仅作为一个基类 其他类。

      抽象类有以下 特点:

      • 抽象类无法实例化
      • 抽象类可能包含抽象方法和访问器。
      • 不能用sealed修饰符修改抽象类,这意味着该类不能被继承。
      • 从抽象类派生的非抽象类必须包含所有继承的抽象方法和访问器的实际实现

      【讨论】:

      • @Hunter 谢谢,正确的'抽象类不能被实例化。但是,为什么我们不能创建它的对象,尽管它可能包含公共或受保护的构造函数。是否有任何逻辑或框架限制?
      • 框架已经被定义为当我们使用关键字“Abstract”时,它不能被实例化,只能被继承。
      【解决方案4】:

      抽象类应该至少有一个没有实现的虚拟方法或属性。这是用 abstract 关键字标记的。如果继承类本身不是抽象的,则它们必须提供一个实现。您不能创建抽象类的实例,因为它没有完整的实现。如果是这样,则不应首先将其标记为摘要。

      【讨论】:

      • 错了。没有抽象成员的抽象类没有任何问题。
      • 有趣。也许您可以提供一个合理的示例,说明没有抽象方法或属性的抽象类在哪里有意义。
      • 汤姆,好的:class Car: Vehicle {}。你能想出一个很好的例子来拥有一个instance的Vehicle吗?
      • @HenkHolterman:Vehicle 不是一个很好的例子,因为它几乎肯定应该有一些抽象成员,例如 MakeModel。另一方面,一个类可以有两个成员,每个成员都根据另一个成员定义;一些派生类可能会覆盖第一个,其他的可能会覆盖第二个,有些则两者兼而有之。例如,封装序列的类型可能包括ToArrayToList 方法,第一个调用ToList().ToArray(),第二个调用new List(ToArray())。当且仅当另一个被覆盖时,每个作为默认行为才有意义。
      【解决方案5】:

      作为其他答案的补充,您可能无法创建抽象类的实例,但您当然可以通过抽象类型引用派生类型的实例并使用抽象中定义的方法或属性基地。

      abstract class A
      {
          public abstract void D();
          public void E() { }
      }
      
      class B : A
      {
          public override void D() { }
      }
      
      class C : A
      {
          public override void D() { }
      }
      

      ...

      A a = new B();
      a.D();
      a.E();
      
      List<A> list = new List<A>() { new B(), new C() };
      

      【讨论】:

      • 这就是扩展抽象类和继承的区别:使用抽象类类型的子类的对象可以访问子类中引入的方法,即没有在抽象类中声明的方法。使用超类类型(继承)的子类的对象无法访问子类中引入的方法。
      【解决方案6】:

      简单来说,抽象类就像一个类的外壳。并非所有方法都有实现,例如缺少某些线段的电路。虽然大部分都可以构建,但用户可以根据需要在这些部分中插入电线和电阻器。

      至于为什么 Java 不允许你创建它,它的一部分只是一个故障保护(只要你不调用未实现的方法,许多抽象类无需任何添加就可以正常工作)。

      【讨论】:

        【解决方案7】:

        如果我们有一个包含纯虚函数的类,那么这个类就是抽象的。如果我们将创建抽象类的对象并调用没有主体的方法(因为该方法是纯虚拟的),则会出错。这就是为什么我们不能创建抽象类的对象。

        【讨论】:

        • 如果抽象类的默认构造函数是公共的,那么它将允许在任何地方创建一个对象,然后如果我们当时出现错误,它就是实现的一部分所以,我不认为这是你解释的强有力的理由。很抱歉在这里弄脏了我的手:(
        • 抽象类有一个受保护的构造函数(默认情况下)允许派生类型对其进行初始化。
        【解决方案8】:

        我们不能为抽象类bcoz创建对象,大多数抽象类都包含“抽象方法”,所以抽象方法是不完整的方法。所以我们无法估计这些方法将占用多少内存。这是其中之一为什么我们不能为抽象类创建对象。

        【讨论】:

          【解决方案9】:

          这是一个类似的 StackOverflow 问题。简而言之,在抽象类上有一个公共构造函数是合法的。有些工具会警告您这样做没有意义。

          Whats the utility of public constructors in abstract classes in C#?

          【讨论】:

            【解决方案10】:

            实际上,当我们创建一个普通类的对象时,我们使用 Constructor 来分配内存 对于像

            这样的对象
            myclass obj=new myclass();
            

            这里使用constructorr clr 根据实例变量和方法确定对象需要多少内存。但是对于抽象类,我们无法预测所需的内存量,因为我们没有实现抽象方法,因此无法创建对象。

            【讨论】:

            • 类实例使用的内存与方法的实现无关。方法的代码占用了与类本身相关的空间,而不是该类的对象。在每个对象中存储方法的代码有什么意义?
            【解决方案11】:

            当我们在抽象类中创建一个纯虚函数时,我们在 VTABLE 中为函数保留了一个槽(在上一个主题中研究过),但没有在该槽中放置任何地址。因此 VTABLE 将不完整。

            由于抽象类的 VTABLE 不完整,因此编译器将不允许为此类创建对象,并且在您尝试这样做时会显示错误消息。

            来源Study Tonight

            【讨论】:

              【解决方案12】:

              参考studytonight

              当我们在抽象类中创建一个纯虚函数时,我们保留一个 VTABLE 中函数的插槽(在上一个主题中研究过),但没有 将任何地址放入该插槽中。因此 VTABLE 将不完整。

              由于抽象类的 VTABLE 不完整,因此编译器 不会为此类创建对象,并会显示 每当您尝试这样做时都会出现错误消息。

              【讨论】:

                【解决方案13】:

                对不起各位...

                当且仅当该抽象类不包含任何抽象方法时,您才能为抽象类创建对象。

                这是我的示例。复制它并编译运行。

                abstract class Example {
                  void display(){
                    System.out.println("Hi I am Abstract Class.");
                  }
                }
                
                class ExampleDemo {
                    public static void main(String[] args) {
                        Example ob = new Example(){};
                        ob.display();
                   }
                }
                

                所以你的答案是肯定的,如果它不是抽象方法,我们可以为抽象类创建对象。 检查我的程序。

                【讨论】:

                • 这样你并不是在创建一个Example类的对象,而是在创建一个匿名类的对象
                • 对不起,没有。您正在创建一个动态创建的匿名内部类的实例。尝试在您的ob 对象上使用getClass(),您会看到。
                【解决方案14】:

                我不同意接受的答案。原因是我们可以拥有纯虚函数的体。

                答案是:

                当我们在类中创建一个纯虚函数时,我们在 VTABLE 中为函数保留了一个槽,但不会在该槽中放置任何地址。因此 VTABLE 将是不完整的。 由于抽象类的 VTABLE 不完整,因此编译器不会允许为此类创建对象,并且每当您尝试这样做时都会显示错误消息。

                【讨论】:

                • @Davesh - 接受答案在所问问题的范围内。您的答案围绕已接受的答案。这是设计使然,您正在将某些东西路由到虚拟功能。纯虚函数不在抽象类的范围内。我不能接受你的回答,除非其他技术人员升级你的回答。
                • @Devesh:这与语言无关。许多语言还允许没有抽象方法的抽象类,而 vtable 等实现细节与此无关。
                【解决方案15】:

                我们也可以像这样为抽象类创建对象...

                public class HelloWorld
                {
                    public static void main(String args[])
                    {
                        Person p = new Person()
                        { 
                            void eat()
                            {
                                console.writeline("sooper..");
                            } 
                        }; 
                        p.eat();
                    }
                }
                abstract class Person
                { 
                    abstract void eat(); 
                } 
                

                【讨论】:

                • 这实际上是一个匿名类的对象,而不是抽象类的对象
                • 匿名类意味着该类不应该有任何名称。但是这里我们有一个名为person的抽象类,这怎么可能是一个匿名类。
                • 很难在评论中解释这一点。但是这里有一个类似的问题:stackoverflow.com/questions/5154533/…
                • 我同意这在 cmets 中很难解释,这不是提出问题的最佳示例。它可能与设计的匿名类型有关(在我看来,可能是其他人可以反对的)。在msdn中有很好的解释:msdn.microsoft.com/en-us/library/bb397696.aspx
                • 有办法简单解释。 p 的运行时类本身是动态创建的,作为扩展 Person 的匿名内部类,具有给定的方法。如果你在你的对象上使用getClass(),它不会返回Person类对象,而是一个名为Helloworld$1的类(Helloworld的第一个匿名内部类)。
                【解决方案16】:

                每个人都在写抽象类有一些没有定义的虚函数。由于这个原因,我们不能创建对象,但是抽象类是一个带有关键字“抽象”的类,它可能有也可能没有抽象方法。我认为这是一个概念,它不需要任何记忆。因此,如果我们可以创建一个对象 den,那么将创建一个不可能的内存,由于这个原因,我们无法创建抽象类的对象,但我们可以创建它的引用,它不占用任何内存位置。

                【讨论】:

                • 请使用正确的语言,您的帖子读起来很烦人。这可能就是为什么尽管内容可能有意义,但您却被否决了。
                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2011-07-05
                • 1970-01-01
                • 1970-01-01
                • 2013-12-03
                • 1970-01-01
                • 2012-07-04
                • 1970-01-01
                相关资源
                最近更新 更多