如何从抽象类中创建对象?

4

我们知道C#中的Array类是抽象的。

但是,该类的静态CreateInstance方法会返回一个Array类对象。

这是如何实现的呢?


2
一个更好的问题是,“为什么你认为这是不可能的?”假设Animal是一个抽象类,这是否意味着你不能有一个返回Animal的方法?你能解释一下为什么你认为这是不可能的吗? - Eric Lippert
谢谢Eric。我以为CreateInstance方法会直接返回Array类对象。 - Hojjat
6个回答

6

描述

不,您不能创建抽象类的实例。

MSDN:抽象类与接口密切相关。它们是无法实例化的类,通常是部分实现或根本未实现。抽象类和接口之间的一个关键区别是,类可以实现无限数量的接口,但只能继承一个抽象(或任何其他类型的)类。从抽象类派生的类仍然可以实现接口。在创建组件时,抽象类很有用,因为它们允许您在某些方法中指定不变的功能水平,但在需要该类的特定实现之前留下其他方法的实现。它们也很好地实现了版本控制,因为如果派生类中需要其他功能,则可以将其添加到基类而不会破坏代码。

更多信息


4

这是一个静态工厂方法,用于返回一个数组实例。该示例创建了一个长度为10的整数值类型数组。

System.Array myIntArray = Array.CreateInstance(typeof(int),10);

这应该能为您提供更多详细信息 http://msdn.microsoft.com/en-us/library/zb3cfh7k.aspx


2
方法Array.CreateInstance()有多个重载,它们的返回类型都被定义为Array,实际上Array是一个抽象类。但是它们返回的对象类型并不直接是Array,而是一些从Array继承的类型(具体是哪种类型取决于使用的重载和传入的参数)。
例如:
Array a = Array.CreateInstance(typeof(int), 10); //create some array
Type type = a.GetType(); // type is int[], which is not abstract
Type baseType = type.BaseType; // baseType is Array

基本上,这与以下工厂方法的原理相同:

abstract class Animal
{
    public static Animal CreateInstance(AnimalType animalType)
    {
        if (animalType == AnimalType.Cat)
            return new Cat();
        if (animalType == AnimalType.Dog)
            return new Dog();
        // etc.
    }
}

这里,Animal是一个抽象基类型,CatDog是继承自Animal的具体类型,animalType告诉我们该方法应返回哪种类型。
现在,在.Net中,数组在几个方面被特殊处理(例如,有针对处理数组的IL指令)。但它们不是类型系统中的例外(除了可能是数组协变)。

1

Array 似乎是抽象类的一个特例。从我在 文档 中所读到的,我建议 Array 的创建和函数在 .NET Framework 代码中被内部处理 - 很可能广泛使用本地代码以获得更好的性能结果。我认为这就是为什么这个类被设计成抽象的原因。

如果有更了解 .NET Framework 内部机制的人可以改进我的答案,我会很高兴。


@HojjatEsmaeilzadeh: 现在,在 .Net 中,数组在多个方面都被特殊处理(例如,有专门用于处理数组的 IL 指令)。 这实际上就是我想说的 - 只是不知道具体细节 :) - Sergey Kudriavtsev

0

我认为与这种情况相关的最佳方式是考虑一个返回接口实例的方法!!!

你知道,我们不能创建接口的实例,但是在内部,一个方法可能知道实现该接口的类,并返回该类的实例。


-1
namespace ConsoleApplication1
{
    public class Circle : Shape
    {
        public override void Draw()
        {
            Console.WriteLine("Draw a Circle");
        }
    }

    public abstract class Shape
    {    
        public abstract void Draw();
    }
}

你可以这样做。
class Program
{
    static void Main(string[] args)
    {       
        Shape v;
        v = new Circle();
        v.Draw();
    }
}

1
请花点时间阅读[编辑帮助](//stackoverflow.com/editing-help)中的内容。在Stack Overflow上进行格式设置与其他网站不同。 - Dharman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接