最新文章
泰课新年学课蛇来运转欢度春节活动
02-01 20:25
共庆2024圣诞、元旦泰课双蛋活动
12-16 10:21
泰课共庆75周年国庆活动!
10-05 21:24
暑假双月联动学习计划 7月15 - 8月21日
07-14 23:09
泰课在线劳动光荣,勤学快乐之五月勤学季活动
04-30 21:19
2024年青春绽放开学季活动
03-11 13:01
关于Activator.CreateInstance到底创建的是什么的一个问题
昨天,有位同学提出了这样一个问题:
Controller c = Activator.CreateInstance(typeof(StarUpCommand)) as Controller;
c.Execute(data);
其中,StarUpCommand 类继承自 Controller 类,Controller 类有一个 abstract Execute() 抽象方法,而 StarUpCommand 类重写(override)了该 Execute() 方法。
问题是:c 现在被声明为 Controller 类型的一个实例,那么 c.Execute(data) 为什么会调用到 StarUpCommand.cs 里的 Execute() 方法呢?
我一开始没太理解这位同学的思路,尝试这样回答:
Activator.CreateInstance 方法创建了一个 StarUpCommand 对象的实例,然后通过 as 操作符将其类型转换为 StarUpCommand 的父类(即 Controller 类)。
显然,同学还是不太明白,继续追问:
c 为什么是 StarUpCommand 的实例而不是 Controller 的实例呢?Activator.CreateInstance(typeof(StarUpCommand)) 创建的是 StarUpCommand 类的实例,但经过 as 转换为 Controller 类型,并且 c 的声明也是 Controller 类,那么 c 应该是 Controller 类的实例才对啊?
这个问题问得很有意思,乍一看好像确实如此。于是,我继续举了个例子,该例子来源于 这里。
假设 myObj 是一个已经存在的对象,我们来看下面的代码:
object myClass = new object();
myClass = Activator.CreateInstance(myObj.GetType());
这样一来,myClass 就完全拥有了 myObj 的方法和属性。
接下来,我们深入分析一下 Activator.CreateInstance 方法。该方法的定义如下:
public static object CreateInstance(Type type);
它返回的是一个 object 类型的对象。为什么要这样设计呢?这是因为 Activator.CreateInstance 方法通过反射机制(可以理解为一种在运行时分析类型信息的技术),摸清了指定类型(这里是 StarUpCommand 类)有哪些属性和方法,然后依据这些信息创建了一个对象实例并返回。但在这个过程中,该方法并没有直接使用 StarUpCommand 类的具体定义(就好像没有该类的“图纸”),所以只能返回一个通用的 object 类型对象。
既然这个对象实际上已经具有了 StarUpCommand 类的属性和方法,那么自然可以将其类型转换为它的父类或者基类。在我们的例子中,通过 as 操作符将其转换为 Controller 类型。虽然 c 被声明为 Controller 类型,但它实际上引用的是 StarUpCommand 类的实例,所以当调用 c.Execute(data) 时,会调用到 StarUpCommand 类中重写的 Execute() 方法,这体现了面向对象编程中的多态性。多态性允许我们通过基类的引用调用派生类中重写的方法,从而提高代码的灵活性和可扩展性。