c#专题—基类的重写

一、c#支持重写实例方法和属性,但是不支持重写字段和任何静态成员,为了进行重写,需要将需要重写的成员用virtual关键字标记。
如下:
1)方法的重写

 class Father
    {
        public virtual  void MyActor()
        {
            Console.WriteLine("我是父亲");
        }
    }


    class Me:Father
    {
        public override  void MyActor()
        {
            Console.WriteLine("我是自己");
        }
       
    }
    class Son:Me
    {
        public override  void MyActor()
        {
            Console.WriteLine("我是儿子");
        }
    }

调用如下:

Father father = new Me();
            father.MyActor();

调用的结果是:我是自己

所以我们可以看出当调用Father类的虚方法时,调用的就是实例化的子类的对象方法。
2)属性的重写

class MyFather
    {
        private int _Age;
        public virtual int Age
        {
            get
            {
                if (_Age < 100 && _Age > 0)
                {
                    return _Age;
                }
                else
                {
                    return 0;

                }
            }
            set
            {

                _Age = value;

            }


        }
    }
  class  MyBrother:MyFather
    {
        public override int Age//语法糖
        {
            get => base.Age;//使用这个特殊的符号代替了括号和return
            set => base.Age = value;
        }
    }
  class My : MyFather
    {
        public override int Age 
        {
            get
            {
               return base.Age;
            }

            set
            {
                base.Age=value ;
            }
        }
    }

二、如果我们声明了虚方法,但是又不想重写该方法,但是程序中又报了警告,那么我们该怎么办?我们应该使用new关键字把父类的方法隐藏起来,等到真正调用的时候其实调用的还是父类声明的虚方法,如下:

 class Father
    {
        public  virtual void MyActor()
        {
            Console.WriteLine("我是父亲");
        }
    }


    class Me:Father
    {
        public new   void MyActor()
        {
            Console.WriteLine("我是自己");
        }
       
    }
    class Son:Me
    {
        public new  void MyActor()
        {
            Console.WriteLine("我是儿子");
        }
    }

调用如下:

  Father father = new Son();
        father.MyActor();

调用结果如下:

我是父亲

结果不是我们想象的他会调用Son类中的方法,他会调用父类的方法,说白了new操作符不能实现重写虚方法的功能,只能移除编译器警告。

三、Sealed修饰符

1)密封类中不能有virtual修饰的虚拟成员,否则会报错
在这里插入图片描述
2)密封类禁止从该类派生
在这里插入图片描述
3)密封成员无法在派生类中被重写
在这里插入图片描述
所以如果我们不想让一个类的成员被重写,就将这个成员用sealed修饰符修饰就好。

四、base成员
1)base的作用一个是在子类中调用父类的成员,如下:

  class A
    {
        public virtual void Method()
        {

        }
    }

    class B:A
    {
        public  override void  Method()
        {
            Console.WriteLine("我是B类");
        }

    }

    class C:B
    {
        public override void Method()
        {
            Console.WriteLine("我是C类");
        }

    }

    class D:C

    {
        public override void Method()
        {
            base.Method();
        }
    }

调用如下:

   A a = new D();
            a.Method();

调用结果:

我是C类

说明base只是调用当前子类的父类的成员,但是不会一直调用到最上层的基类的成员。
2)在基类有很多个构造函数的时候。

  class A
    {

        public string Name { get; set; }
        public int Age { get; set; }


        //public A()
        //{

        //}


        public A(string name)
        {
            this.Name = name;
        }

        public A(string name, int age)
        {
            this.Name = name;
            this.Age = age;
        }


        public virtual void Method()
        {

        }
    }

    class B : A
    {
        public B(string name):base(name)
        {

        }
        public override void Method()
        {
            Console.WriteLine("我是B类");
        }

    }

    class C : B
    {
        public C(string name) : base(name)
        {

        }
        public override void Method()
        {
            Console.WriteLine("我是C类");
        }

    }

    class D : C

    {

        public D(string name) : base(name)
        {

        }
        public override void Method()
        {
            base.Method();
        }
    }

上面的代码中,分为三种情况:
1)基类没有构造函数,也就是有一个隐藏的无参的构造函数
那么子类不需要使用Base来调用基类的构造函数;
2)基类有一个无参的构造函数
子类不需要使用Base来调用基类的构造函数;
3)基类一个有参的构造函数
子类必须使用Base来调用这个无参的构造函数;
4)基类有多个有参的构造函数
子类至少要使用Base来调用基类的一个构造函数,否则
5)基类有多个有参的构造函数,同时有一个无参的构造函数
子类默认调用基类无参的构造函数。

五、抽象类

 abstract  class A
    {

        public string Name { get; set; }
        public int Age { get; set; }


        //public A()
        //{

        //}


        public A(string name)
        {
            this.Name = name;
        }

        public A(string name, int age)
        {
            this.Name = name;
            this.Age = age;
        }
       
        public virtual void VirtualMethod()
        {

        }
        public abstract void Method();
    }

    class B : A
    {
        public B(string name):base(name)
        {

        }
        public override void Method()
        {
            Console.WriteLine("我是B类的method");
        }

        public override void VirtualMethod()
        {
            Console.WriteLine("我是类B的virtualmethod");
        }

    }

如果我们就是想在父类中声明一些虚的成员(抽象成员),至于具体的实现都是在子类中,我们就可以将父类声明为抽象类(abstract修饰),然后在抽象类中声明抽象成员,这些抽象成员使用abstract修饰就好,或者virtual,这里说说一下virtual和abstract修饰的成员的区别:
1)virtual修饰的成员比如方法必须有实现,哪怕是只有一对大括号的空实现,但是abstract修饰的成员不允许有实现;
2)virtual修饰的成员可以被子类重写,也可以不被重写,程序不会报错,但是abstract修饰的成员一定要在子类中实现;
3)抽象类中virtual修饰的已经在父类中实现地成员没有意义,因为抽象类无法实例化。

六、所有的类都从object类派生,并且内置了诸如Equals、ToString、MemberwiseClone这些虚方法。

七、is操作符:

 class A
    {

        public string Name { get; set; }
        public int Age { get; set; }


        //public A()
        //{

        //}


        public A(string name)
        {
            this.Name = name;
        }

        public A(string name, int age)
        {
            this.Name = name;
            this.Age = age;
        }
       
        public virtual void VirtualMethod()
        {

        }
       
    }

    class B : A
    {
        public B(string name):base(name)
        {

        }
       

        public override void VirtualMethod()
        {
            Console.WriteLine("我是类B的virtualmethod");
        }

    }

调用如下:

 A a = new A("");
            B b = new B("");



            if (a is object)
            {
                Console.WriteLine("true");
            }
            else
            {
                Console.WriteLine("false");
            }

            if (b is object)
            {
                Console.WriteLine("true");
            }
            else
            {
                Console.WriteLine("false");
            }

            if (b is A)
            {
                Console.WriteLine("true");
            }
            else
            {
                Console.WriteLine("false");
            }
            if (a is B)
            {
                Console.WriteLine("true");
            }
            else
            {
                Console.WriteLine("false");
            }

结果:

true
true
true
false

说明通过is操作符可以判断子类对象是不是属于父类,而且所有类型都是属于object。
八、as操作符

   A a = new A("");
        B b = new B("");

        A aa = b as A;
        if(aa==null)
        {
            Console.WriteLine("转换失败");
        }
        else
        {
            Console.WriteLine("转换成功");
        }

        B bb = a as B;
        if (bb == null)
        {
            Console.WriteLine("转换失败");
        }
        else
        {
            Console.WriteLine("转换成功");
        }

结果:

转换成功
转换失败

上面代码说明子类可以直接转换为父类,但是父类不能直接转换为子类。
as操作符实现类型的转化,当转换失败的时候,就返回一个null,避免了抛出异常。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

c#上位机

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值