当前位置:编程学习 > C#/ASP.NET >>

我已经快被base关键字和继承弄疯了

我已经被微软的“莫名奇妙”快搞晕了,学C#难道都是拿来主义?根本没有原理可言,给你就直接用,连本质都还没知道


以上请怒我抱怨一下微软,下面开始提问:
为什么一个子类继承父类,同时运用(virtual,override)知识覆盖了父类的方法,但是最后在子类里面竟然能通过base访问到该方法,莫名其妙。。。。既然已经被覆盖了,应该已经不存在了
(注意:首先我理解的继承,就是:之所以派生类能无条件访问父类的成员,是因为派生类内隐形的写出了所有父类的成员)
class A
    {
        public virtual void Fn()
        {
            Console.WriteLine("我是父类中的方法");
        }
        
    }
    class B : A
    {
        public virtual void Fn()
        {
            Console.WriteLine("我是父类中的方法");//因为B继承A,所以在B中存在A的所有成员,但是用户看不到,就当是隐身的代码
        }

        public override void Fn()
        {
            Console.WriteLine("我是子类中的方法,并且我想替换父类中的方法");
        }
        public void SSSSS()
        {
            Console.WriteLine("我已经用自己的Fn()替换掉了父类中的Fn(),现在我已经访问不到父类中的Fn()了");
            base.Fn()//我试试看能不能访问
            Console.WriteLine(我了个艹,居然还能访问到!!!!!!!);
        }
    }
--------------------编程问答-------------------- 不是被覆盖,是被隐藏,base.XXX就是为了访问父类的属性方法 --------------------编程问答-------------------- 同时运用(virtual,override)知识,这个不是覆盖吧,这个是对父类方法的重写,并没有修改父类的方法。
重写方法是指子类在继承父类的基础上,重新实现父类中的方法,并没有修改父类的方法! --------------------编程问答-------------------- override 没有改变父类,改的是自己继承后的代码
引用 1 楼 thedolphin 的回复:
不是被覆盖,是被隐藏,base.XXX就是为了访问父类的属性方法
--------------------编程问答--------------------
引用 3 楼 thedolphin 的回复:
override 没有改变父类,改的是自己继承后的代码
引用 1 楼 thedolphin 的回复:

不是被覆盖,是被隐藏,base.XXX就是为了访问父类的属性方法



我知道父类本身的代码没有改变,我认为是改变了“存在于子类中的父类成员”
懂我的意思吗?
也就是说,我认为,B类如果继承A类,那么B类的内部就含有A类的所有成员。当运用virtual,override覆盖的是B类内的A类方法,而base正是访问B类内的A类成员 --------------------编程问答--------------------
引用 2 楼 zhaoyanzhe 的回复:
同时运用(virtual,override)知识,这个不是覆盖吧,这个是对父类方法的重写,并没有修改父类的方法。
重写方法是指子类在继承父类的基础上,重新实现父类中的方法,并没有修改父类的方法!


我知道父类本身的代码没有改变,我认为是改变了“存在于子类中的父类成员”
懂我的意思吗?
也就是说,我认为,B类如果继承A类,那么B类的内部就含有A类的所有成员。当运用virtual,override覆盖的是B类内的A类方法,而base正是访问B类内的A类成员 --------------------编程问答-------------------- --------------------编程问答--------------------
引用 6 楼 caozhy 的回复:
1L 2L 都是错的。

我不知道lz想说什么,但是明显,这个问题很奇怪,估计是lz先入为主地,莫名奇妙地认为,覆盖方法有阻止派生类访问基类成员的作用,发现不是这么回事才奇怪。

但是这就好比一个人问为什么冰箱不能加热食物一样。提问的人困惑,别人更困惑。

如果你希望“隐藏”什么,直接定义成private就可以了。
class Base
{
    private void fo……




晕,完全不是这个意思 --------------------编程问答--------------------
引用楼主 dazitou 的回复:
以上请怒我抱怨一下微软,下面开始提问:
为什么一个子类继承父类,同时运用(virtual,override)知识覆……


首先1楼的代码是无法通过编译的。类B中已经有了两个同样签名的Fn方法。

另外,你对覆盖的理解不对。
父类中的虚函数可以被子类覆盖或者叫重写。
这个覆盖是指在通过类的实例调用方法;
而你所举的例子SSSSS()是在类B中对方法的实现。
举个例子,希望你能看懂区别和虚方法是怎样用的。

    class Program
    {
        static void Main(string[] args)
        {
            A a = new A();
            a.Fn(); // ==> "A"
            A b = new B();
            b.Fn(); // ==> "B", 虽然b的申明类是A,但这里调用的是B类中的Fn()方法。
        }
    }

    class A
    {
        public virtual void Fn()
        {
            Console.WriteLine("A");
        }
    }

    class B : A 
    {
        public override void Fn()
        {
            Console.WriteLine("B");
        }
    } --------------------编程问答--------------------
引用 5 楼 dazitou 的回复:
我知道父类本身的代码没有改变,我认为是改变了“存在于子类中的父类成员”
懂我的意思吗?
也就是说,我认为,B类如果继承A类,那么B类的内部就含有A类的所有成员。当运用virtual,override覆盖的是B类内的A类方法,而base正是访问B类内的A类成员


首先什么叫做“B类的内部还有A的员”?你充其量也只能说是“B类对象实例内部还有一个A类对象实例”吧!

其次,这是胡说八道地歪曲面向对象概念。B类对象实例充当A类对象,是因为实实在在地B类对象实例就是A类对象实例,而不是什么B类的内部包含一个A类对象。

比如说“黑马”是“马”,不是说黑马肚子里含有另外一匹马,而是因为一匹黑马本来就是一匹马。你的那种包含关系是非常有无误导的。

比如说写代码
Person x= new Teacher("张三");
x.喊一声();
那么是在调用什么teacher身体里的另一个人的“喊一声”方法?你就是在调用Teacher的重写了的“喊一声”这个方法。只有Teacher是否还调用了Person上的方法,那是隐藏起来的是七情,x变量根本不知道。 --------------------编程问答-------------------- 隐藏并不代表去掉,只是看调用对象是谁,才能确定调用方法,根本还是要明确调用对象。对象拥有方法 --------------------编程问答-------------------- 如果倒退3、4年前,有人说继承就是子类对象和实例的内部包含一个父类对象实例,我可以理解,因为那时国内有基本很有名c++的入门书上就是这样胡说八道的。

实际上对象继承的标准概念,就是概念上的“消解”概念,而不是说子类对象内部组合类一个父类对象。不管早期的某些低级的c++是不是用那种方式实现的,但是它必须达到测试标准,即上述的代码中,x变量对应的实际的对象的类型就是一个Teacher,而不是一个实例化为Person类型的对象实例。如果你认为对象实例化时是Person类型,那么可以说你的嗲吗基本的跟谁在对话还没有搞清楚。 --------------------编程问答-------------------- 那么可以说你的嗲吗基本的跟谁在对话还没有搞清楚  -->  那么可以说你的代码基本的跟谁在对话还没有搞清楚


sorry,几十分钟前有个mm让我有些把持不住,刚喝完酒回家。 --------------------编程问答-------------------- 请你记住一点,不要从低级的什么c++、汇编的概念去理解面向对象。高级语言的本质就是更加面向对象,而不是以低级语言的实现方式去理解面向对象概念。

多态就好象是接口,你以一个“机械”的概念去使用变量x,但是它其实是实例化为一个水陆两用机械,这才叫做继承和多态。如果你认为所谓“水陆两用机械继承自机械概念”就是说一个水陆两用机械的实体内部有另外一个机械,这本身就丧失了原则了。

继承是一种“is-a”的概念,而不是“has-a”概念。搞清楚这个你就免得机械地去生硬去找什么“派生类内部的父类成员”。 --------------------编程问答--------------------
引用 11 楼 sp1234 的回复:
如果倒退3、4年前,有人说继承就是子类对象和实例的内部包含一个父类对象实例,我可以理解,因为那时国内有基本很有名c++的入门书上就是这样胡说八道的。

实际上对象继承的标准概念,就是概念上的“消解”概念,而不是说子类对象内部组合类一个父类对象。不管早期的某些低级的c++是不是用那种方式实现的,但是它必须达到测试标准,即上述的代码中,x变量对应的实际的对象的类型就是一个Teacher,而不是一……


问题不在于3、4年前。就是倒回几十年前,继承就是子类对象和实例的内部包含一个父类对象实例也是错的。但是,就是今天,子类对象和实例的内部包含一个父类对象实例来实现继承也没错。就像今天下午一个贴子问到什么是多态一样。一群人煞有介事地说,什么动态绑定,静态绑定……

我觉得根本没写过程序的人不要去理解面向对象——无论怎么解释,他们理解的都是错的。如同像小孩子说明什么是结婚。 --------------------编程问答--------------------
引用 9 楼 sp1234 的回复:
引用 5 楼 dazitou 的回复:
我知道父类本身的代码没有改变,我认为是改变了“存在于子类中的父类成员”
懂我的意思吗?
也就是说,我认为,B类如果继承A类,那么B类的内部就含有A类的所有成员。当运用virtual,override覆盖的是B类内的A类方法,而base正是访问B类内的A类成员

首先什么叫做“B类的内部还有A的员”?你充其量也只能说是“B类对象实例内部还有一个A类……



我没说“B类的内部还有A的员”啊,我说的是“B类的内部含有A类的所有成员,而且含有的A类成员代码都是系统自己在后台加的,是隐形的,前台看不到” --------------------编程问答--------------------
引用 13 楼 sp1234 的回复:
请你记住一点,不要从低级的什么c++、汇编的概念去理解面向对象。高级语言的本质就是更加面向对象,而不是以低级语言的实现方式去理解面向对象概念。

多态就好象是接口,你以一个“机械”的概念去使用变量x,但是它其实是实例化为一个水陆两用机械,这才叫做继承和多态。如果你认为所谓“水陆两用机械继承自机械概念”就是说一个水陆两用机械的实体内部有另外一个机械,这本身就丧失了原则了。

继承是一种“i……



我可以再问个问题吗?网上某资料说:
  “override重写继承自基类的virtural方法,可以理解为拆掉老房子,在原址上建新房子,老房子再也找不到了(基类方法永远调用不到了)”

以上是原话,但是明明可以用base调用到基类的方法啊
--------------------编程问答-------------------- 你看到的base.xxx的代码是“B类调用A类成员”吗?是B类对象实例调用A类代码吧?!

什么叫做继承和多态?一个声明为A类型的变量x假设引用的是一个实际上实例化为B类的对象,那么a.Method就是调用这个B类对象实例的Method方法,我们都知道的,只是你不知道而已。 --------------------编程问答--------------------
引用 13 楼 sp1234 的回复:
请你记住一点,不要从低级的什么c++、汇编的概念去理解面向对象。高级语言的本质就是更加面向对象,而不是以低级语言的实现方式去理解面向对象概念。

多态就好象是接口,你以一个“机械”的概念去使用变量x,但是它其实是实例化为一个水陆两用机械,这才叫做继承和多态。如果你认为所谓“水陆两用机械继承自机械概念”就是说一个水陆两用机械的实体内部有另外一个机械,这本身就丧失了原则了。

继承是一种“i……



貌似我没学过C++啊,我连C都没学过,直接学C#,这是我第一个程序语言 --------------------编程问答-------------------- 玩概念这东西永远也没完,还是来点实际的好,给你个场景:
一张图里面有很多图块(方块、圆圈、复合图块、...), 如果移动图块一种方法是拿到图块,判断类型,然后确定移动方法,而是用继承就简单多了

class DBlock
{
  public virtual void Move()
  {
     preMove() 
   }
   private void PreMove()  //所有图块有共同的移动内容
   {
     //...
   }
}
class Circle:DBlock

  public override void Move()
  {
    CircleMove();
    base.Move();
  }
  private void CircleMove()   //每个特定子类有特定的移动内容
  {}
}


class Diagram
{
  List<DBlock> _BlockLlist;   //这里有方有圆优

   public void MoveAllBlocks
   {
      foreach( DBlock d in _BlockList
      {
         d.Move();  //这多方便呀
      }
   }
 }
  
 

  这仅是继承的一个非常简单的应用,实际用起来时,会有很多技巧。 --------------------编程问答--------------------
引用 14 楼 caozhy 的回复:
引用 11 楼 sp1234 的回复:

如果倒退3、4年前,有人说继承就是子类对象和实例的内部包含一个父类对象实例,我可以理解,因为那时国内有基本很有名c++的入门书上就是这样胡说八道的。

实际上对象继承的标准概念,就是概念上的“消解”概念,而不是说子类对象内部组合类一个父类对象。不管早期的某些低级的c++是不是用那种方式实现的,但是它必须达到测试标准,即上述的代码中,x变量对应的实际……


 搞篇文章 ,让大家学习学习

期待中 --------------------编程问答--------------------
引用 16 楼 dazitou123 的回复:
我可以再问个问题吗?网上某资料说:
  “override重写继承自基类的virtural方法,可以理解为拆掉老房子,在原址上建新房子,老房子再也找不到了(基类方法永远调用不到了)”

以上是原话,但是明明可以用base调用到基类的方法啊


不知道这是哪里来的,也懒得搜索出处了。但是这显然是错误的。B类继承A类,它们的代码放在那里好好地啊。怎么会被人家李代桃僵的呢?

关键地是,搞清楚你的对象是谁,也就是把握住具体的个体,而不要纠缠于变量(代理)声明时代类型。比如说“病人ab76629323c7”,这很可能就是“住院病人ab76629323c7”。你不能说是“住院病人ab76629323c7”肚子里住着一个“病人ab76629323c7”。
--------------------编程问答-------------------- 可以这么说,人是动物,虽然是高级动物,但是避免不了在做某些社会性的事情的时候掺杂一些原始兽性。

比如xxoo……………… --------------------编程问答-------------------- 用base只不过是“激发原始本能”而已,如果你不用,他就没有,表现出来的还是那个新的事物。


如果听到某个人说某个人是“衣冠禽兽”,那真是说的一点都对啊。 --------------------编程问答--------------------
引用 18 楼 dazitou123 的回复:
貌似我没学过C++啊,我连C都没学过,直接学C#,这是我第一个程序语言


如果你有没有1995年以前的编程语言教科书的误导,那么你就要注意是否自己过于机械化地理解概念了。

这就好像我们说“鸭嘴兽是一种哺乳动物”一样,是指概念上的继承关系,而不是把鸭嘴兽跟哺乳动物割裂为两个个体。机械地以为名词不同就是两种东西,那么有可能就无法在编程时运用“一个很自然的个体会有多种类型概念”这个基本的语言学道理。 --------------------编程问答--------------------
引用 16 楼 dazitou123 的回复:
我可以再问个问题吗?网上某资料说:
  “override重写继承自基类的virtural方法,可以理解为拆掉老房子,在原址上建新房子,老房子再也找不到了(基类方法永远调用不到了)”

以上是原话,但是明明可以用base调用到基类的方法啊

任何生硬的解释都很难让人理解,最好的方法就是实际试一试,我的理解他这段话,从意义上讲是这个意思:
  A a=new B();
  a.Fn() 运行的是B上的Fn方法,而不能是A的(虽然A上也有,但被“重定位”了)。   --------------------编程问答-------------------- “老房子取代了新房子”,或者说什么“儿子继承了老子的遗产”,这种都是对继承的严重歪曲。

继承是什么?继承就好象是说“女人也是人”,电脑也是生产资料,白马也是马,等等这类概念。如果说继承是“新电脑取代了电脑、儿子继承了死去父亲的遗产”那种,那么那种作者显然是在害你呢!请把握好这个分寸。

当你在设计程序是,本不应该继承的概念你为了低级的复用一点代码而继承了,那么过不了多久你就会变得晕头转向,你的代码越来越诡异。因为你自己都不相信这是崇尚自然的概念。 --------------------编程问答--------------------
引用 16 楼 dazitou123 的回复:
可以理解为拆掉老房子,在原址上建新房子,老房子再也找不到了


nononono……不是这么理解的,把原址房子拆了重建那是实例化一个新的对象。

应该这么来:
class 住所
{
 public virtual void 居住(object obj)
 {
      //有个门
 }
}
class 住所:人的房子
{
 public override void 居住(object obj) 
 {
      if(obj is Person)
      {
           //装修
            //厕所
            //地板
     
            ....
           base.居住(obj);//用来说明人类居住的房子也得有个门
            ...
           //内部的其他门
      }
      else if(obj is Pig)
      {
          //猪食槽子
            //排便通道
            base.居住(obj);
      }
 }
 
} --------------------编程问答--------------------
引用 25 楼 etudiant6666 的回复:
引用 16 楼 dazitou123 的回复:
我可以再问个问题吗?网上某资料说:
“override重写继承自基类的virtural方法,可以理解为拆掉老房子,在原址上建新房子,老房子再也找不到了(基类方法永远调用不到了)”

以上是原话,但是明明可以用base调用到基类的方法啊

任何生硬的解释都很难让人理解,最好的方法就是实际试一试,我的理解他这段话,从意义上讲是这个意思:
……


是的,其实就是这个意思。但是他的的确确说出了“拆掉老房子,在原址上建新房子,老房子再也找不到了”这段话。而实际上在派生类内又可以使用base访问到所谓的已经被拆掉的房子(也就是A类中的虚拟方法) --------------------编程问答-------------------- “新电脑取代了电脑、儿子继承了死去父亲的遗产”那种  -->  “新电脑取代了旧电脑、儿子继承了死去父亲的遗产”那种


其实过去有很多人奇怪我为什么对这类问题总是不厌其烦地纠正。其实我非常重视最基础的概念。这可能影响你很多年。 --------------------编程问答-------------------- base是来体现继承思想的一个微妙的关键字,用来在关键时刻来体现子类存在的父类特性。 --------------------编程问答--------------------
引用 28 楼 dazitou123 的回复:
是的,其实就是这个意思。但是他的的确确说出了“拆掉老房子,在原址上建新房子,老房子再也找不到了”这段话。而实际上在派生类内又可以使用base访问到所谓的已经被拆掉的房子(也就是A类中的虚拟方法)


再本不该建模为继承的时候去继承,是一种非常恶俗的设计。那种设计是错误的。那种设计应该直截了当地建模为组合或者聚合关系,而不是继承。 --------------------编程问答--------------------
引用 16 楼 dazitou123 的回复:
我可以再问个问题吗?网上某资料说:
  “override重写继承自基类的virtural方法,可以理解为拆掉老房子,在原址上建新房子,老房子再也找不到了(基类方法永远调用不到了)”

以上是原话,但是明明可以用base调用到基类的方法啊


base只能访问父类,因此只有子类可以找到父类的方法,对于外部调用这个子类的其它类来说,这个子类的父类再也找不到了,因此从这个角度来说,那个资料没错,只不过你理解的角度不一样。

当然override并没有拆掉老房子的动作,应该换个角度考虑。访问子类能够访问到所有父类中定义的方法,子类可以偷懒不做任何改动,那么调用的那些方法都是父类中所定义的原样,但是当有需求的时候,在子类中重写部分方法,用override重写后,外部就只能访问子类中重写的方法,而无法再次访问到其父类的方法了(强制类型转换除外),但是子类内部因为需要,还是有可能要用到父类的方法,因此提供了base来访问父类的方法。

总结,base是提供便利性的一个存在,方便实现自定义的类,从已有的类继承可以少写很多代码,如果去掉了base,继承类时,当需要在父类方法基础上扩展时还必须将父类的代码重新抄写一遍,这样显然不是好的做法。 --------------------编程问答--------------------
引用 28 楼 dazitou123 的回复:
是的,其实就是这个意思。但是他的的确确说出了“拆掉老房子,在原址上建新房子,老房子再也找不到了”这段话。


那现在大家都在告诉你,这句话是片面的。

我擦,这么像政治题的答案呢。

好吧,凡事要辩证的来看,“老房子再也找不到了”面对的对象是房子外面的人,因为他们不会使用房子里面的东西。但是对于使用房子里面的东西的人来说,房子还是房子,我拉屎还是要去卫生间,睡觉还是要用床。

这本书如果真的这么片面的说,那就不要继续看了。换书。 --------------------编程问答--------------------
引用 33 楼 sunzongbao2007 的回复:
房子还是房子,我拉屎还是要去卫生间,睡觉还是要用床。


只是卫生间里面没准浴盆换了个新的。睡觉的时候钢丝床换了席梦思,睡觉前铺了个电褥子,还要打开开关。但是最终还是要卫生间还是要提供拉屎的地方,床还是要睡觉的地方。

不要用那个房子的例子来继续想了,那个说的太片面了。 --------------------编程问答-------------------- 27楼有个例子,那个才是需要看的。 --------------------编程问答--------------------
引用 28 楼 dazitou123 的回复:
是的,其实就是这个意思。但是他的的确确说出了“拆掉老房子,在原址上建新房子,老房子再也找不到了”这段话。而实际上在派生类内又可以使用base访问到所谓的已经被拆掉的房子(也就是A类中的虚拟方法)

人家说的也不能说是错的,因为我们用 A a=new B(); B a=new B();只要实例是B类的,调用的Fn()方法都是B类的,调不了A中基类的Fn(), 注意是实例a调不了偶。至于B.Fn()内是否运行了base.Fn() 是另一个问题,就好象新房子用了旧房子的地方和材料 --------------------编程问答--------------------
引用 36 楼 etudiant6666 的回复:
引用 28 楼 dazitou123 的回复:
是的,其实就是这个意思。但是他的的确确说出了“拆掉老房子,在原址上建新房子,老房子再也找不到了”这段话。而实际上在派生类内又可以使用base访问到所谓的已经被拆掉的房子(也就是A类中的虚拟方法)
人家说的也不能说是错的,因为我们用 A a=new B(); B a=new B();只要实例是B类的,调用的Fn()方法都是B类的,调不了A中基类的F……


这个是角度问题。一个内一个外。
对于这种事情,对就是对错就是错,片面的也是错。 --------------------编程问答--------------------
引用 37 楼 sunzongbao2007 的回复:
这种事情


指的是那个什么网上的资料,既然是属于传授型的资料,就应该写的准确不带一丝的歧义。
忘了是螃蟹哥还是sp1234说过,非常反感网上鱼龙混杂,很多人感觉研究出点什么就拿出来发个blog,以传授者的角度来“讲述”。
讲的准确还好,讲的片面就容易糟蹋一群刚刚入门的人。 --------------------编程问答-------------------- 我发现顶楼的这句话了:"(注意:首先我理解的继承,就是:之所以派生类能无条件访问父类的成员,是因为派生类内隐形的写出了所有父类的成员)"

这个理解本身就是错误的,派生类内并未隐形的写出任何父类的成员,只是在访问的时候,如果子类不存在的,就用父类的,子类存在的,就用子类的,编译器不会自动增加任何冗余代码,不会在子类重新写一遍父类的成员。

从实际出发,实践是检验真理的唯一标准,任何大道理,没有实际用途等于白说,任何花哨的语法,没有实际用途就没人会去用。你应该先多用,然后从各种实际场合反推它的好处,而不是先大谈理论,把自己的曲解强加上去,不结合实际谈大道理。等你用多了,自然会觉得这里这样的语法是非常恰当的,有了实际的载体,再理解原先不理解的语法,会非常容易。 --------------------编程问答-------------------- 其实听大家这么说我能理解的
也就是说:
        就算你把房子拆了,建起了新的房子,这的确让旧房子消失了,访问不到了。但是base是个很神奇的东西,它就是有能耐施法让那个“已经被拆掉不存在的房子”访问到

但是这用代码怎么解释呢?首先我对于继承的理解就是:“B继承了A,那么B就能访问到A中的成员,这是因为A的实例成员包含在B中,与B中自带的成员共存。”
比如class A
    {
         void MM()
         {console.ReadLine("我是A的成员")
         }
    }

如果有一个类B继承了类A,那么B的实际代码如下
class B
    {
         void MM()
         {console.ReadLine("我是A的成员")
         }
         void GG()
         {console.ReadLine("我是B的成员")
         }
          
    } --------------------编程问答--------------------
引用 40 楼 dazitou123 的回复:
  就算你把房子拆了,建起了新的房子,这的确让旧房子消失了,访问不到了。但是base是个很神奇的东西,它就是有能耐施法让那个“已经被拆掉不存在的房子”访问到

但是这用代码怎么解释呢?


……到底看没看上面的回复。
这是内外两个层面上看实物,参照点不同,结果不同。 --------------------编程问答--------------------
引用 41 楼 sunzongbao2007 的回复:
引用 40 楼 dazitou123 的回复:
就算你把房子拆了,建起了新的房子,这的确让旧房子消失了,访问不到了。但是base是个很神奇的东西,它就是有能耐施法让那个“已经被拆掉不存在的房子”访问到

但是这用代码怎么解释呢?

……到底看没看上面的回复。
这是内外两个层面上看实物,参照点不同,结果不同。


抱歉刚才没表达好。。我真懂了,
也就是说,父类中的成员被子类中的同名成员覆盖后,外界类不可能通过B类对象访问到A中那个被覆盖的成员。但是作为子类的B能通过一种神奇的方法base访问到A类被覆盖的成员 --------------------编程问答-------------------- 谢谢各位了,我希望高手能加我QQ,我现在都是在自学C#,有时候的确会遇到困难不能很快的解决。 --------------------编程问答--------------------
引用 43 楼 dazitou123 的回复:
谢谢各位了,我希望高手能加我QQ,我现在都是在自学C#,有时候的确会遇到困难不能很快的解决。

在网上看资料要多参考几份 --------------------编程问答-------------------- 看了这么多,是不是继承就是将一个模糊的概念实例化。比如说人是class A,女人就是对class A的继承? --------------------编程问答--------------------
引用 40 楼 dazitou123 的回复:
其实听大家这么说我能理解的
也就是说:
        就算你把房子拆了,建起了新的房子,这的确让旧房子消失了,访问不到了。但是base是个很神奇的东西,它就是有能耐施法让那个“已经被拆掉不存在的房子”访问到

  ……

别老拆房子拆房子的了,这个比喻本来就是错的。好好理解理解sp1234说的吧。 --------------------编程问答-------------------- 这楼盖的够快的啊!! --------------------编程问答-------------------- 其实是没理解多态,楼主换本书吧

--------------------编程问答-------------------- --------------------编程问答--------------------
A x= new B();
x.Fn();

这是调用A中的Fn代码?

那你就还没有理解面向对象的继承概念。由于x兼容于A接口,所以编译器允许我们这样写代码,并且给我们生成了最终的代码。但是这里x所引用的对象就是一个B实例。

子类可以在继承时还去对消父类的方法,是否理解这个是面向对象和结构化编程的分水岭。其实这个问题意义很大。 --------------------编程问答-------------------- 再往深了盖层楼,
使用继承的时候,初始化对象要比初始化单类慢20%左右(具体数字跟基类中的成员数有关),而运行子类的方法(包括基类方法)速度就没有下降了,你有兴趣可以思考一下为什么?
1)为什么初始化会多出20%时间,而运行不会增加?
2)为什么增加了时间人们还会用它?
  真理解了这两个问题,你才算真的懂了,不然脑子里还是一堆绛紫。 --------------------编程问答-------------------- --------------------编程问答-------------------- 自己没学好,就抱怨起微软来了?
其他的不说,你真想隐藏基类方法的话就在子类中加个new关键字来声明。
base是为了在写派生类时方便对父类的访问。
至于你的问题,就是奇怪,你还不如问:“爸爸,我为什么要叫你爸爸啊?” --------------------编程问答-------------------- 呵呵............. --------------------编程问答-------------------- 似乎好像,我在第一篇帖子就已经回答过了

你自己去看《你必须知道的.net》

我只想说一句,你到底看了没。真有这个闲功夫发5篇帖子,直接去看这本书即可

第一个帖子就已经说明白了,这就是魔术,魔术的本质原本就是你以为他消失了,其实没有,他根本还在那里,观众的眼睛看不到他在那里,不等于魔术师本人不知道他在那里 --------------------编程问答-------------------- 《你必须知道的。net》图


鸡 继承与 鸟

你以为鸟的showtype就消失了??其实没有,他还在那里 --------------------编程问答-------------------- 分清楚,你的角色

你到底是观众,魔术师助手,魔术师本人

其实通用程序员担当是魔术师助手,也就是也能“看”到东西到底在那里

lz错误是你把自己当观众了,你认为你眼睛看不见了,他就消失了。其实做为助手,你就应该知道他并没消失,他原本就在 --------------------编程问答-------------------- 我已经被微软的“莫名奇妙”快搞晕了,学C#难道都是拿来主义?根本没有原理可言,给你就直接用,连本质都还没知道
-------------------------------------------------
你说的话才莫名其妙,等你有了一两年开发经验,你再回头看这句话,保证你嘴角一撇,会笑的。 --------------------编程问答-------------------- 这么好用的特性居然被楼主说的一文不值!!!


为什么要用base?

因为如果在继承类里面要用到基类的成员就需要用到!这是最大限度的继承和灵活性的考虑。
--------------------编程问答-------------------- 覆盖??

没有覆盖这一说
--------------------编程问答-------------------- 我表示无语! --------------------编程问答--------------------


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;



using System.Collections;
using System.Collections.Specialized;
using MyNewMultimap;



namespace MyNewMultimap
{

    public class MyMultimap : SortedList
    {

        public MyMultimap()
        {            
        }

        public override  object this[object key]
        {
            get
            {
                if (this.IndexOfKey(key) >= 0)
                {
                    List<object> o = (List<object>)base[key];
                    return o;
                }

                return null;
            }

            set
            {
                if (this.IndexOfKey(key) >= 0)
                {
                    List<object> o = (List<object>)this[key];
                    o.Add(value);

                    return;
                }
                                
                List<object> ol = new List<object>();
                ol.Add((object)value);

                
                base[key] = ol;
                
            }
        }
    }
}


namespace Multimap
{
    class Program
    {
        static void Main(string[] args)
        {
            MyMultimap mm = new MyMultimap();


            mm["fruit"] = "banana";
            mm["fruit"] = "orange";
            mm["fruit"] = "potato";

            mm["programme language"] = "C++";
            mm["programme language"] = "C#";
            mm["programme language"] = "Delphi";

            // search
            int n = mm.IndexOfKey("programme language");
            if(n >= 0)
            {
                List<object> l = (List<object>)mm["programme language"];

                for (int i = 0; i < l.Count; i++)
                    Console.WriteLine(l[i]);
            }

        }
    }
}

--------------------编程问答-------------------- 不懂的话看看这个例子,多重映射是怎么实现的?

【名词解释】:
多重映射: 指一个主键可以映射多个值,例子,一个年级可以有多个班级1班、2班、3班... 那么年级到班级的映射就是多重映射
map<int, int> mapGradeClass;
mapGradeClass[1] = 30; // 1年级第一个班级30人
mapGradeClass[1] = 20; // 1年纪第二个班级20人
mapGradeClass[1] = 35; // 1年级第三个班级35人

mapGradeClass[4] = 30; // 4年级第一个班级30人
mapGradeClass[4] = 20; // 4年纪第二个班级20人
mapGradeClass[4] = 35; // 4年级第三个班级35人 --------------------编程问答-------------------- 好可怜的微软,让我想起了两句话。
1、错的不是我,是这个世界。
2、哼,别想吓倒我,这一切都是幻觉。 --------------------编程问答-------------------- virtual,override这个是对外而言。。。。
对类本身没有任何意义 --------------------编程问答-------------------- virtual 和abstract你需要先搞清楚 --------------------编程问答--------------------

    public class Test1
    {
        public virtual string Method1()
        {
            return "123";
        }
    }

    public override class Test2 : Test1
    {
        public override string Method1()
        {
            return "333";
        }
    }
    //下面调用Method1方法
    Test1 t = (Test1)new Test2();
    string str = t.Method1();
    //这时候 str的值为333
    // 若Test2中不是用override 而是用new的话 得出的结论就是 123
    //这样应该可以看出override的意思了吧
--------------------编程问答--------------------

    public class Test1
    {
        public virtual string Method1()
        {
            return "123";
        }
    }

    public class Test2 : Test1
    {
        public override string Method1()
        {
            return "333";
        }
    }
    //下面调用Method1方法
    Test1 t = (Test1)new Test2();
    string str = t.Method1();
    //这时候 str的值为333
    // 若Test2中不是用override 而是用new的话 得出的结论就是 123
    //这样应该可以看出override的意思了吧
--------------------编程问答-------------------- 继承的理解应该是“白马非马”,也就是说白马只是马的一种,而不能把白马理解成是所有马,所以说白马是继承马而来的,所以“马”是父类,“白马”是子类,“白马”包含“马”的所有特征和功能,但是“马”却不能包含“白马”的所有特征和功能,所以父类(“马”)是调用不了子类(“白马”)的所有特征,但是子类(“白马”)却可以调用父类("马")的所有特征和功能。

至于“拆老房,建新房”,简直就不是一回事,怎么能比喻成继承关系呢?!!! --------------------编程问答-------------------- base关键字是十分有必要的。

在重写(overrride)的方法中,我们在很多情况下都要把基类的实现执行一次,再补充子类的实现。你不要告诉我,你是从基类把代码copy过来的吧? --------------------编程问答-------------------- 看玩这多的回复,有以下感触
1.首先,继承和多态是中思想。理解非常重要。
2.这思想体现在计算机系统里面,最常见有几种
1)继承父类 2)继承接口 3)其他
从内存角度说,A父类的方法存在一个方法区域,其子类B也有个方法区域
如果B某方法M(public权限)使用new 把A类的某方法M隐藏了(我是这么理解的,当然有人不认同)B类没有权限去访问A类的M方法。只能访问自己的M方法。
假设C继承A,使用override重写M方法。(我是这么理解的,当然有人不认同)
C类只是把A的M方法具体实现给修改了,但是M方法还是A的,A申明了M方法体或称完全方法签名。M方法还是A的。即使A的M方法使用abstract,virtual关键字修改,M方法还是A的,只是派生类把具体实现改写了。
base关键字给你权限去访问你的父类(链表是就近原则向上搜索)
另外,覆盖是C++的说法,好像在纯虚函数,多态种使用非常多。 --------------------编程问答-------------------- virtual 和 override表现了面向对象的多态性,这怎么会是覆盖呢?
补充:.NET技术 ,  C#
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,