继承与重写

    在对象与类那一篇中我们讲了什么是类和对象,而在现实生活中,很多事物都有相同或相似的特征,当我们将这些事物写成类,会发现有很多重复的属性或方法,试想,如果将这些重复性的代码只写在一个类,而其他的类都能使用,那不就大大减少了代码量了吗?因此就有继承的思想了。

    继承是面向对象程序设计中最重要的概念之一。继承允许我们根据一个类来定义另一个类,这使得创建和维护应用程序变得更容易。同时也有利于重用代码和节省开发时间。
    当创建一个类时,程序员不需要完全重新编写新的数据成员和成员函数,只需要设计一个新的类,继承了已有的类的成员即可。这个已有的类被称为的基类,这个新的类被称为派生类。

    继承的思想实现了 属于(IS-A) 关系。例如,哺乳动物 属于(IS-A) 动物,狗 属于(IS-A) 哺乳动物,因此狗 属于(IS-A) 动物。

    下面我们来了解关于继承的一些知识:

基类和派生类

    一个类只能派生自一个类,但能继承多个接口,这涉及到多重继承,下面我们会具体介绍。

class B{
  public int age; 
  private string name;
}
class A:B{
  public int weight;
}

上面代码中A类继承了B类,所以B类就叫做基类(也叫父类),而A类叫做派生类(也叫子类)

A类继承了B类,所以不仅有自己的字段weight,还有父类的age和name。

构造函数的继承

    当父类的构造函数有无参的时,子类可以定义自己的构造函数而不受父类影响

    当父类的构造函数没有无参的时,则子类必须传值。

    例如:

class Father{
  private int age; public int Age{
    get{return age;}
  }
  public Father(int age)
  { 
    this.age=age;
  }
}
class Son:Father{
  public Son(int a):base(a)
  {
    
  }
}

C#多重继承

前面我们说过,C#不支持继承多个类,但支持继承多个接口,通过继承多个接口,我们实现了多重继承。

例如:

class A{
  public int age;
}
public interface IB{
  void Run();
}
public interface IC{
  void Eat();
}
class D:A,IB,IC{

}

上面我们定义了父类A和接口IB和IC,类D同时继承了A、IB和IC,即多重继承

注意:父类写在接口前面


方法的重写

问题一:什么是重写?

    “重写”父类方法就是修改它的实现方式或者说在子类中对它进行重新编写。

问题二:为什么要重写父类的方法
    通常,子类继承父类的方法,在调用对象继承方法的时候,调用和执行的是父类的实现。但是,有时候需要对子类中的继承方法有不同的实现方式。例如,假设动物存在“跑”的方法,从中继承有狗类和马类两个子类;
问题三:如何重写

    重写父类的方法要用到override关键字(具有override关键字修饰的方法是对父类中同名方法的新实现)要重写父类的方法,前提是父类中该要被重写的方法必须声明为virtual或者是abstract类型。给父类中要被重写的方法添加virtual关键字表示可以在子类中重写它的实现。(注意:C#中的方法默认并不是virtual类型的,因此要添加virtual关键字才能够被重写)

virtual关键字用于将方法定义为支持多态,有virtual关键字修饰的方法称为“虚拟方法”

new表示重写方法,但是没有覆盖效果,提醒程序员该方法是重写

[访问修饰符] virtual [返回类型] 方法名(参数列表)
{
  //虚拟方法的实现,该方法可以被子类重写

}

例如:

class Animal{
  public virtual void Run(){
  //该方法可能会被子类进行扩展,所以用virtual修饰
    Console.WriteLine("跑步");
  }
}

class Bird:Animal{
  public override void Run(){//重写覆盖父类中同名方法
    Console.WriteLine("两条腿跑步");
  }
}

向上转型:

父类 f=new 子类();里氏替换原则

f.方法()先找继承的方法,找不到就找子类中同名的方法; 下面在控制台实现:

class Chinese{
  public void Mandarin(){
    Console.WriteLine("中国人讲普通
话");
  }
  public virtual void Eat(){
    Consolw.writeLine("中国人吃");
  }
  public virtual void Mores(){
    Consolw.writeLine("中国人风俗");
  }
}
class Shenzhen:Chinese{ 
  public void Cantonese(){
    Console.WriteLine("深圳人讲粤语话");
  }
  public void Eat(){
    Consolw.writeLine("深圳人吃");
  }
  public override void Mores(){
    Consolw.writeLine("深圳人风俗");
  }
}

实例化:

Shenzhen s=new Shenzhen();//优先调用自己的方法
s.Mandarin();
s.Cantonese();
s.Eat();
s.Mores();
Chinese c=s;//优先调用继承的方法
c.Mandarin();
//c.Cantonese();没有权限调用讲阅读,因为中国人里面没有讲粤语的方法
c.Eat();
c.Mores();

控制台输出

中国人讲普通话 

深圳人讲粤语

深 圳 人 吃 

深圳人风俗

中国人讲普通话 

中国人吃

深圳人风俗//子类重写覆盖了父类的方法

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值