在对象与类那一篇中我们讲了什么是类和对象,而在现实生活中,很多事物都有相同或相似的特征,当我们将这些事物写成类,会发现有很多重复的属性或方法,试想,如果将这些重复性的代码只写在一个类,而其他的类都能使用,那不就大大减少了代码量了吗?因此就有继承的思想了。
继承是面向对象程序设计中最重要的概念之一。继承允许我们根据一个类来定义另一个类,这使得创建和维护应用程序变得更容易。同时也有利于重用代码和节省开发时间。
当创建一个类时,程序员不需要完全重新编写新的数据成员和成员函数,只需要设计一个新的类,继承了已有的类的成员即可。这个已有的类被称为的基类,这个新的类被称为派生类。
继承的思想实现了 属于(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();
控制台输出
中国人讲普通话
深圳人讲粤语
深 圳 人 吃
深圳人风俗
中国人讲普通话
中国人吃
深圳人风俗//子类重写覆盖了父类的方法