首页 新闻 赞助 找找看

关于父类指向子类对象的引用的问题

0
悬赏园豆:30 [已解决问题] 解决于 2014-07-17 19:47
  public class Person
    {        
       
    }

    public class Student : Person
    {
        public string test()
        {
            return "test";
        }
    }

 

 Person p1 = new Student();
 Console.WriteLine(p1.GetType());
 Console.WriteLine(p1.GetType().GetMethod("test").Invoke(p1, null));

问题1:第二行表明P1是个Student类型的,但是它却不可以调用Student的增加的

 

方法,这是为什么?

2:用反射又可以调用了?

happydaily的主页 happydaily | 菜鸟二级 | 园豆:301
提问于:2014-07-16 18:17
< >
分享
最佳答案
0

 

 

 

 

 

 

问题1:第二行表明P1是个Student类型的,但是它却不可以调用Student的增加的

 方法,这是为什么?

"Person p1" - 你把变量声明为了Person类型,虽然它实际上是Person的子类Student类型,但是编译器只能认为它是Person类型,Person类没有test方法,所以你编译不能通过。

C# 是静态语言,编译时要做类型检查,虽然你现在代码里把变量的声明和赋值放在一起,一眼就能看到p1是什么类型,但是你想想,如果p1是个方法的参数呢?编译器根本不能知道调用方传给它的是哪个具体类型,只能按声明的类型检查。(你不能调用test方法是编译器不让你调,要让编译器不做检查,可以试试dynamic关键字。)

2:用反射又可以调用了?

p1.GetType()和反射都是在代码执行时,这时候公共语言运行时从元数据中获取类型信息,可以知道p1的实际类型,所以可以动态调用。(只要p1.GetType()和p1.GetType().GetMethod("test").Invoke(p1, null)语法没有错误,也没有静态调用对象不存在的方法,编译没问题)。

 

 

 

 

 

 

收获园豆:30
C#开发人员 | 初学一级 |园豆:181 | 2014-07-17 13:22

Console.WriteLine(p1.GetType());显示为"student",是编译器错了还是不应该这样得到P1的类型?

happydaily | 园豆:301 (菜鸟二级) | 2014-07-17 17:17

@happydaily: p1.GetType()返回当前实例的运行时类型,也就是具体的类。

http://msdn.microsoft.com/zh-cn/library/system.object.gettype(v=vs.110).aspx

编译器也没有错,编译器只认你变量声明的类型,你声明了"Person p1",p1的编译期类型就是Person。这样设计是有道理的,因为在编译期编译器并不能确定运行时p1一定是什么类型的。例如下面的代码:

public string Method1(object p1)
{
         p1.Test();
}

你看看上面的代码,参数声明是object类型的,你随意传个object子类都可以,object子类太多了,编译器怎么知道你将来调用方法时传的参数对象有没有Test方法呢?如果没有就会出错了。

严格检查是静态语言的特点 ,为了保证类型安全,在编译期就能多发现错误。而一些动态、弱类型语言,例如javascript就不做严格检查,运行时发现调用了对象没有的方法,才报异常。

C#开发人员 | 园豆:181 (初学一级) | 2014-07-17 18:44

@C#开发人员: 谢谢你的热心指导!

happydaily | 园豆:301 (菜鸟二级) | 2014-07-17 19:47
其他回答(5)
0

对于p1来说,test方法是隐藏的。而反射是从对象中找方法,所以又能找到test方法。

抱歉,能力有限,还真解释不清楚~

幻天芒 | 园豆:37175 (高人七级) | 2014-07-16 20:05
0

object类型是所有类型的基类, 如果object能调用所有子类的方法,

你觉得还能写代码不?

Firen | 园豆:5385 (大侠五级) | 2014-07-17 08:58
0

看右边的类型就行,反射是 根据对象分配的类型,不是根据  左边的 引用指针类型。

Qlin | 园豆:2403 (老鸟四级) | 2014-07-17 09:16
0

运行时才能确定p1是student,编译时不能确定

wolfy | 园豆:2636 (老鸟四级) | 2014-07-17 13:31
0

用父类引用指向子类对象的时候,这个引用只具人父类对象中的方法。

就像我们有时候返回一个List<T>对象的时候会用Ilist<T>,这个时候我们就只能使用Ilist<T>提供的方法。

这是机制问题,不用纠结!

Alex_QY1987 | 园豆:1888 (小虾三级) | 2014-07-17 14:08
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册