c#中父类引用指向子类对象问题深究:
我遇到的问题和好多新手一样,我对父类引用指向子类对象一直相当的茫然开始,后来自己理解为:父类的引用在栈中建立,用指针指向了子类在堆中开辟的内存空间,当用构造方法赋值的时候...
我遇到的问题和好多新手一样,我对父类引用指向子类对象一直相当的茫然开始,后来自己理解为:父类的引用在栈中建立,用指针指向了子类在堆中开辟的内存空间,当用构造方法赋值的时候,父类接收赋值同时把该值存储到了子类开辟的内存空间中,这里同时子类单有的字段也就赋值并存储在内存空间中,当用父类引用进行“.”操作的时候只能显示出来父类的字段值(也就是存储在内存中子类对象的值),这样理解对吗?如果对,当我把返回的父类引用加入到集合中,为什么把子类的字段属性也加进去了?
class AutomobileFactory
{
public static Automobile makeautomoblie(string no,string name,string color,int year,double dailyRent,int load ,string type)
{
Automobile automobile = null;
switch (type)
{
case "Car": automobile = new Car(no, name, color, year, dailyRent); break;
case "Truck": automobile = new Truck(no, name, color, year, dailyRent, load); break;
}
return automobile;
}
}
在这里 Automobile 是父类 有no, name, color, year, dailyRent字段属性,car是一个子类,没有自己的字段属性都继承父类,truck是另外一个子类,他继承父类同时也有自己的一个属性字段load,当return的时候返回一个Automobile类型的引用,他包括了父类的属性,也有truck的load的属性,调试出来的结果!!只不过是用"."操作不能点出来!这是为什么?? 展开
class AutomobileFactory
{
public static Automobile makeautomoblie(string no,string name,string color,int year,double dailyRent,int load ,string type)
{
Automobile automobile = null;
switch (type)
{
case "Car": automobile = new Car(no, name, color, year, dailyRent); break;
case "Truck": automobile = new Truck(no, name, color, year, dailyRent, load); break;
}
return automobile;
}
}
在这里 Automobile 是父类 有no, name, color, year, dailyRent字段属性,car是一个子类,没有自己的字段属性都继承父类,truck是另外一个子类,他继承父类同时也有自己的一个属性字段load,当return的时候返回一个Automobile类型的引用,他包括了父类的属性,也有truck的load的属性,调试出来的结果!!只不过是用"."操作不能点出来!这是为什么?? 展开
5个回答
展开全部
你的问题非常的好。
你加进集合中的的确是子类的实例,关键是你用什么类型的引用指向这个子类的实例。关于你调用子类的属性或者方法是要和它的引用类型吻合的,并不是子类实例的所有东西都一定能够调用到。这个是面向对象的一个重要的特性。
举个例子:
接口IA里有方法: fa()
接口IB里有方法: fb()
子类C实现(继承)了接口IA,IB,并且子类自己定义了个方法fc(),则子类C就有:fa(),fb(),fc()三个方法
当子类C的实例objC被IA类型的引用指向的时候[IA objC = new C()或者(IA)objC],你可以调用到的是fa(),通俗的说objC这里是IA类型的,而并不是C类型的,所以只能调IA的fa()
当子类C的实例objC被IB类型的引用指向的时候[IB objC = new C()或者(IB)objC],你可以调用到的是fb(),通俗的说objC这里是IA类型的,而并不是C类型的,所以只能调IB的fb()
当子类C的实例objC被C类型的引用指向的时候[C objC = new C()或者(C)objC],你可以调用到的是fa(),fb(),fc()
这个其实就是面向接口或者说是面向对象编程的一个内容
你加进集合中的的确是子类的实例,关键是你用什么类型的引用指向这个子类的实例。关于你调用子类的属性或者方法是要和它的引用类型吻合的,并不是子类实例的所有东西都一定能够调用到。这个是面向对象的一个重要的特性。
举个例子:
接口IA里有方法: fa()
接口IB里有方法: fb()
子类C实现(继承)了接口IA,IB,并且子类自己定义了个方法fc(),则子类C就有:fa(),fb(),fc()三个方法
当子类C的实例objC被IA类型的引用指向的时候[IA objC = new C()或者(IA)objC],你可以调用到的是fa(),通俗的说objC这里是IA类型的,而并不是C类型的,所以只能调IA的fa()
当子类C的实例objC被IB类型的引用指向的时候[IB objC = new C()或者(IB)objC],你可以调用到的是fb(),通俗的说objC这里是IA类型的,而并不是C类型的,所以只能调IB的fb()
当子类C的实例objC被C类型的引用指向的时候[C objC = new C()或者(C)objC],你可以调用到的是fa(),fb(),fc()
这个其实就是面向接口或者说是面向对象编程的一个内容
展开全部
哈哈,你想知道底层的东西么?那我就告诉你,在底层中,一个变量是有类型的,而一个对象呢,也差不多算有类型的,在进行变量赋值的时候,CLR会检查是否可以允许赋值,如果是子类赋值给父类,或者子类给所实现接口类赋值的话,就可以。
当使用父类变量实际操作子类的时候,赋值字段其实在底层上和直接操作子类变量没区别,而调用方法则会使用callvirtual调用,这样CLR会根据实际情况调用父类或者子类方法(这情况讲起来挺复杂的)
想彻底的了解这个东西,你需要学的还很多很多很多,我都是学了将近两年才逐渐理解的,别着急,慢慢来。
回答补充:
这就是说,其实对象在内存中是不会考虑什么类型的,他有什么字段就是有什么字段,但是对象类型和变量类型是两码事,你不敢保证你的变量拥有什么别的方法,比如汽车类,那么轿车对象和卡车对象都可以赋给汽车的变量,但是你在写代码的时候敢保证他一定就是卡车,一定就有载货这个方法么?也许你敢保证,但是C#编译器不敢,所以点不出来
我建议你学学反射,会让你知道其实对象不管赋给什么类型的变量,其实本身没有变化,都是那个对象,只不过你看到的,你能用到的,所谓的广义的接口,是不同的。
当使用父类变量实际操作子类的时候,赋值字段其实在底层上和直接操作子类变量没区别,而调用方法则会使用callvirtual调用,这样CLR会根据实际情况调用父类或者子类方法(这情况讲起来挺复杂的)
想彻底的了解这个东西,你需要学的还很多很多很多,我都是学了将近两年才逐渐理解的,别着急,慢慢来。
回答补充:
这就是说,其实对象在内存中是不会考虑什么类型的,他有什么字段就是有什么字段,但是对象类型和变量类型是两码事,你不敢保证你的变量拥有什么别的方法,比如汽车类,那么轿车对象和卡车对象都可以赋给汽车的变量,但是你在写代码的时候敢保证他一定就是卡车,一定就有载货这个方法么?也许你敢保证,但是C#编译器不敢,所以点不出来
我建议你学学反射,会让你知道其实对象不管赋给什么类型的变量,其实本身没有变化,都是那个对象,只不过你看到的,你能用到的,所谓的广义的接口,是不同的。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
【当用父类引用进行“.”操作的时候只能显示出来父类的字段值(也就是存储在内存中子类对象的值),这样理解对吗?】
不对,父类引用子类的实例,其实这个对象属于子类的类型,但编译器会误认为这个对象是父类的类型(因为编译器只看它的申明类型),所以“.”操作仍然会调用父类的方法和属性,这一过程在编译时就已经完成了绑定,
但是如果这个方法是虚方法(用virtual修饰),情况就不一样了,编译的时候CLR如果判断该方法是虚方法,就会等到运行时才去晚绑定,所以在运行时这个类型该是什么类型就会调用相应的方法,
不对,父类引用子类的实例,其实这个对象属于子类的类型,但编译器会误认为这个对象是父类的类型(因为编译器只看它的申明类型),所以“.”操作仍然会调用父类的方法和属性,这一过程在编译时就已经完成了绑定,
但是如果这个方法是虚方法(用virtual修饰),情况就不一样了,编译的时候CLR如果判断该方法是虚方法,就会等到运行时才去晚绑定,所以在运行时这个类型该是什么类型就会调用相应的方法,
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
其实父类引用指向子类的时候,只要稍作调试就会知道是怎么回事。
第一父类对象引用子类的时候父类对象只是一个说明,而真正实例化得则是子类对象,这就好比经纪人和歌手的关系,经纪人接到命令,真正干活的是歌手一样
第一父类对象引用子类的时候父类对象只是一个说明,而真正实例化得则是子类对象,这就好比经纪人和歌手的关系,经纪人接到命令,真正干活的是歌手一样
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
好抽象啊,大哥给个程序啊。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询