方法在new修饰符的作用下是如何调用的(子类对象赋值给父类变量)

.Net技术 码拜 10年前 (2015-05-10) 1068次浏览 0个评论
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace IL_Method_Test
{
    public class Father
    {
        public void DoWork()
        {
            Console.WriteLine("Father.DoWork()");
        }
    }

    public class Son :Father
    {

        public new void DoWork()
        {
            Console.WriteLine("Son.DoWork()");
        }
    }

   

    class Program
    {
        static void Main(string[] args)
        {
            Father son=new Son();
            son.DoWork();
            Son newSon = new Son();
            newSon.DoWork();

            Console.Read();
        }
    }
}

第一个son.DoWork();为什么会调用父类的方法
第二个我知道原因,new覆盖了
第一个没覆盖?还是应为变量的原因,编译的时候内部有个方法表?变量时哪个类的就调用哪个类的方法?除非被子类override?,能说说原理吗

10分
有两个毫无关系都叫DoWork的方法,
用基类类型访问,访问的是基类的,用子类类型访问,访问的是子类的(子类隐藏了基类的方法)。

根本不是“覆盖”。

10分
你记住一点,如果父类定义了一个方法,并且没有用virtual修饰它,那么无论如何你用父类类型调用它,都没有办法调用成子类定义的那个方法。
    public class Father
    {
        public void DoWork() //不加virtual
        {
            Console.WriteLine(“Father.DoWork()”);
        }
    }
 
    public class Son :Father
    {
 
        public new void DoWork()
        {
            Console.WriteLine(“Son.DoWork()”);
        }
    }
你永远不可能试图实现
Father f = new Son();
f.DoWork(); //调用除Father.DoWork以外的另一个方法。
new是隐藏,override才是覆盖,你把子类中的new改成override,就会调用子类的方法了。
另外你的Son newSon = new Son();
            newSon.DoWork();
这个根本不是覆盖,就是直接调用的son的dowork
首先谢谢caozhy您的回答
Father son=new Son();
构建了一个Son类的对象却赋值给了Father类的变量,是不是这个变量相当于简洁的变成了下面这个样:
Father son=new Father();
但又不完全是这个意思?
子类隐藏了父类的方法,是不是表示这个子类有两个一样的方法,只是有个不能调用?
你没有明白什么叫继承

Father son=new Son();
构建了一个Son类的对象却赋值给了Father类的变量
Father son这是定义了什么?
你认为是定义了一个Father类型的变量叫son
错!
这是定义了一个Father或它的派生类型的变量叫son。

注意这个理解的差异,比如
IDispose d;
这是定义了什么?
定义了一个IDispose接口类型的变量?
接口都没有实现,哪里来的接口类型。

如果你按照我说的就很好理解了,定义了一个实现了IDispose接口的任意类型的变量。

什么叫隐藏?
Son son = new Son();
son.DoWork()按理说因为Son继承了Father,那么应该调用Father.DoWork(),但是因为你又定义了一个重名的变量叫DoWork()所以它“隐藏了”那个DoWork()。

我们用变量名的隐藏类比下:
class A
{
    private int i = 123;
    public void foo1()
    {
        int i;
        i = 456;
    }
    public void foo2()
    {
        Console.WriteLine(i);
    }
}
调用
A a = new A();
a.foo1();
a.foo2(); //输出多少?

显然是123而不是456,为什么,因为foo1()中定义了一个也叫i的变量(和局部变量i毫无关系),并且修改的是那个i,那个i就隐藏了作为局部变量的i。
能不能不隐藏呢?
    public void foo1()
    {
        int i;
        this.i = 456;
    }
这样就输出456了。

一个道理,如果你写
Son son = new Son();
son.DoWork();你调用的和基类的那个毫无关系。如果你像调用基类的,只能转化为基类的类型(如果前面给i加上this表明它是局部变量的i一样)
((Father)son).DoWork();

caozhy
您看看我的想法是不是正确(刚学C#)我自己想的:
所以你可以看到,new去隐藏基类方法,是一种很变态很无聊的用法,最可笑的是,一些傻X老师会非要让初学者去学习它,其实你一辈子不用它,也不知道它最好。
一个变量代表一个值
一个函数代表一个功能

这是小学生都能想明白的事情

为什么明明不同的两个功能,非要起一个名字?我觉得你能想明白这个问题比去理解方法隐藏怎么用更有意义。

我知道您说的意思了,刚才没说完,就发帖了,您看看我下面说的
我如果定义了一个Son的新方法:

 public void DoWork1()
        {
            Console.WriteLine("Son.DoWork1()");
        }

Father son=new Son();
这个son是无权访问这新方法的
如果强制类型转换成Son是可以访问的
是不是说明new Son()以后在堆里已经创建了对象,也有Son的全部方法。但是父类无权访问,内部是怎么控制的?
是不是有个方法权限表?
其实我想知道的就这个

我现在懂了,非常感谢您
引用 6 楼 caozhy 的回复:

你没有明白什么叫继承

Father son=new Son();
构建了一个Son类的对象却赋值给了Father类的变量
Father son这是定义了什么?
你认为是定义了一个Father类型的变量叫son
错!
这是定义了一个Father或它的派生类型的变量叫son。

注意这个理解的差异,比如
IDispose d;
这是定义了什么?
定义了一个IDispose接口类型的变量?
接口都没有实现,哪里来的接口类型。

如果你按照我说的就很好理解了,定义了一个实现了IDispose接口的任意类型的变量。

那这样说的话,son调用的应该是子类的方法啊

引用 13 楼 wenyideren 的回复:
Quote: 引用 6 楼 caozhy 的回复:

你没有明白什么叫继承

Father son=new Son();
构建了一个Son类的对象却赋值给了Father类的变量
Father son这是定义了什么?
你认为是定义了一个Father类型的变量叫son
错!
这是定义了一个Father或它的派生类型的变量叫son。

注意这个理解的差异,比如
IDispose d;
这是定义了什么?
定义了一个IDispose接口类型的变量?
接口都没有实现,哪里来的接口类型。

如果你按照我说的就很好理解了,定义了一个实现了IDispose接口的任意类型的变量。

那这样说的话,son调用的应该是子类的方法啊

那等于我白说了。你的逻辑真强大。
我再重复一次:
son和Son类型没有任何关系。
好比
int STRING = 1;
你说STRING是什么类型?当然还是int类型
Father son,你说son是什么类型?当然还是Father类型。
那它怎么能认识派生类定义的方法呢?


CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明方法在new修饰符的作用下是如何调用的(子类对象赋值给父类变量)
喜欢 (0)
[1034331897@qq.com]
分享 (0)

文章评论已关闭!