ReC# : 多态插曲

从零系列的插曲,前天被问到了一个这样的问题:如何用父类实例去调用子类方法。恕我当时学业不精对多态认识还是不到位,今天就此问题稍作研究。

 class Animal {
        public string Name;
        public Animal() {
            this.Name = "Animal";
        }

        public void Called() {
            Console.WriteLine("Animal");
        }
    }

 class Cat : Animal {
        public Cat() {
            this.Name = "Cat";
        }
        public void Called() {
            Console.WriteLine("Cat");
        }
        public void Called(string str) {
            Console.WriteLine(str);
        }
        public void Called1() {
            Console.WriteLine("NoCat");
        }
    }

为了实际验证一下如何才能达到父类调用子类的方法,我创建了一个Animal类包含一个简单的方法用来检测。然后派生了一个子类Cat,并重载了父类的方法Called(str),和添加了一个新方法Called1。

   Animal animal = new Animal();
           Cat cat = new Cat();

 animal.Called();
            cat.Called();
            cat.Called("YesCat");
            cat.Called1();

首先是简单测试一下,输出结果正常:分别是Animal 、Cat、YesCat、NoCat
接着就是测试父类如何调用子类了。

      Animal animal1 = new Cat();

声明一个Animal类型的变量animal1,用子类去创建它的实例。上面这句话的意思就是Animal类型的引用去指向一个Cat类实例,因为new 在内存上的是一个Cat类。按这个道理来想那么直接就可以调用子类方法呀,于是...

            animal1.Called();
            animal1.Called("YesCat");
            animal1.Called1();

高高兴兴写了这三行然后按下了启动,(⊙v⊙)......
并不能启动...( ⊙ o ⊙ )
很显而易见animal1中无法调用Called(str)和Called1这两个方法。
原因是:在编译的时候Animal类型中不包含对Called(str)方法和Called1()方法的定义,编译将会报错。于是乎注释了下面条:

            animal1.Called();
            //animal1.Called("YesCat");
            //animal1.Called1();

可喜可贺,返回的结果是Animal
这说明了Animal类型的引用虽然指向了Cat类,但是只能访问Cat类中所继承的Animal类方法。
那要如何才能调用子类的方法呢?
这就需要使用强转或者as

 (animal1 as Cat).Called();
            (animal1 as Cat).Called("YesCat");
            (animal1 as Cat).Called1();

返回的结果是:Cat、YesCat、NoCat
恩,这就实现了父类调用子类方法的目的。

as 与 强转的区别

as 只支持引用类型的转换,且不会抛出异常。
强转则支持值类型和引用类型,在转换不匹配时会抛出异常。

你可能感兴趣的:(ReC# : 多态插曲)