美文网首页
c#面向对象3--继承(base)/new隐藏父类同名成员/里氏

c#面向对象3--继承(base)/new隐藏父类同名成员/里氏

作者: Mona_Song | 来源:发表于2021-03-26 17:06 被阅读0次
    • 面向对象三大特征:封装、继承、多态

    Tips:
    1.把两个类写在同一个命名空间下的做法是错误的,适用于教学,不适用于项目开发;真正的项目每一个类都应该存在于一个单独的类文件;

    • 封装:信息隐藏,把一个功能拿出来封装成一个方法;

    1.继承:

    • 使用情景:若多个类中都有重复的代码,可以把这些重复的代码拿出来组成一个新类,作为他们的父类。(父类对子类,基类对派生类)
    • 子类继承了什么:
      1.子类继承了父类的属性和方法,但是没有继承父类的私有字段。
      2.子类没有继承父类的构造函数。但是,子类会默认的调用父类无参数的构造函数,在子类内部创建一个父类对象,让子类可以使用父类中的成员。(所以,如果父类写了一个有参数的构造函数,默认无参数的构造函数就被干掉了,子类就调用不到了,所以这时子类会报错)
    • 解决方法:
      1.在父类中重新写一个无参数的构造函数;
      2.在子类中显示地调用父类的构造函数,使用关键字:base();
      用:base()显示调用父类的有参构造函数

    base

    class Program
        {
            static void Main(string[] args)
            {
                Person[] p = new Person[2];
                p[0] = new Person();
                p[1] = new Chinese();
                foreach (var item in p)
                {
                    item.sayHello();
                }
            }
            public class Person
            {
                public virtual void sayHello()
                {
                    Console.WriteLine("father class: Person");
                }
            }
            public class Chinese:Person
            {
                public override void sayHello()
                {
                    base.sayHello(); //这里base是调用了父类的SayHello方法,base相当于父类对象的作用
                }
            }
        } 
    
    上图运行效果
    • 继承的特性
      1.继承的单根性:一个子类只能有一个父类;
      2.继承的传递性:祖宗的迟早是我的;

    • 查看类图:右键当前命名空间-->视图-->查看类图


      如何查看类图
    • 注意:c#中所有类都直接或间接的继承自Object类(当我们定义一个类的时候,如果没有写:继承一个类,那么这个类就继承了object类)

    2. 关键字new的作用

    • new的作用
      1、创建一个对象
      2、隐藏从父类那里继承过来的同名成员。隐藏的后果就是子类调用不到父类的方法。


      父类Person类中的方法
    子类Reporter类中的同名方法
    • 如果没有这个new关键字,会隐式的隐藏父类中继承过来的同名方法(“生成”之后可以看到子类的SayHello方法下面画绿线);有了new关键字之后,显示隐藏。
    • 启示:子类中不要起跟父类中方法名字相同的方法,否则调用不到(隐式或显示的隐藏了)

    3.里氏转换

    • 里氏转换
      1.子类可以赋值给父类:如果有一个地方需要一个父类作为参数,我们可以给一个子类代替。
      2.如果父类中装的是子类对象,那么可以将这个父类强转为子类对象

    • 子类对象可以调用父类的成员,但是父类对象永远都只能调用自己的成员。

    子类可以赋值给父类:例1

    1.这里需要一个object类型的可变数组
    2.使用object的子类string类型的可变数组填充
    子类可以赋值给父类:例2
    把子类Student赋值给父类Person
    父类强转为子类对象:例1
    1.p中装的是子类对象
    2.将这个父类对象p强转为子类对象ss,调用子类方法成功说明强转成功
    转换失败案例:引出as,is
    这里不能转换成功,会报异常(因为父类中装的是student对象,现在却想转换成teacher对象)

    4.AS/IS

    • is:表示类型转换,如果能够转换成功,返回一个true,否则返回一个false;


      划线处表示,如果p能转换成Teacher的对象,返回true,否则返回false(这里返回false)
    • as:表示类型转换,如果能够转换则返回相应的对象,否则返回一个null


      这里不能转换为Teacher类对象,所以返回值为null
      这里可以转换为Student类对象,所以返回了Student类对象,可以成功调用方法

    5.练习

    • 练习题目:输出十次打招呼,每次打招呼都是随机的。因此每次执行结果不一样;执行效果如下图所示;


      练习题目执行效果
    • 用到随机数
      random r = new random();
      int rNumber = r.Next(1,7);这里(1,7)的意思是可以产生1-6的随机数;

      循环的目的是为了给每个person类的对象赋初值,注意这里random的用法
      这些对象调用方法时只能调用Person类的对象,因为即使装的是子类的对象,表现出来的仍然是父类Person类型的
      为了解决上图的问题,用到 is和类型强制转换

    6.Protected

    • Protected:可以在当前类的内部以及该类的子类中访问。
    • public:所有类都可访问。
    • private:仅在当前类内部可以访问。

    相关文章

      网友评论

          本文标题:c#面向对象3--继承(base)/new隐藏父类同名成员/里氏

          本文链接:https://www.haomeiwen.com/subject/dogxhltx.html