继承
在类之间建立一种相交的关系,使得新定义的派生类的实例可以继承已有的基类的特征并且还可以添加新的功能
特点
-
派生类是对基类的扩展,派生类可以添加新的成员,但不能移除已经继承的成员的定义
-
继承是可以传递的。如果C从B中派生,B又从A中派生,那么C不仅继承了B中声明的成员,同样也继承了A中声明的成员
-
构造函数和析构函数不能被继承,除此之外其他成员能被继承。基类中成员的访问方式只能决定派生类能否访问它们
-
派生类如果定义了与继承而来的成员同名的新成员,那么就可以覆盖已继承的成员,但这兵不是删除了这些成员,只是不能再访问这些成员
-
类可以定义虚方法、虚属性及虚索引指示器,它的派生类能够重载这些成员,从而使类可以展示出多态性。
-
派生类只能从一个类中继承,可以通过接口来实现多重继承
基础实现
class Program
{
static void Main(string[] args)
{
Man man = new Man();
man.Eat();
//在派生类中访问基类中的成员一般有2种方式,一是调用base.<成员> 调用基类的方法,二是显示类型转换为父类
((People)man).Eat();
}
}
public class People
{
public People()
{
Console.WriteLine("父类:人");
}
public void Eat()
{
Console.WriteLine("父类:人吃饭");
}
}
class Man:People
{
public Man()
{
Console.WriteLine("子类:男人");
}
public void WhoEat()
{
base.Eat();
}
}
隐藏基类成员
//当派生类需要覆盖基类的方法时,C#使用new修饰符来实现隐藏基类成员
class Program
{
static void Main(string[] args)
{
Man man = new Man();
man.Eat();
}
}
public class People
{
public People()
{
Console.WriteLine("父类:人");
}
public void Eat()
{
Console.WriteLine("父类:人吃饭");
}
}
class Man:People
{
public Man()
{
Console.WriteLine("子类:男人");
}
public new void Eat()
{
Console.WriteLine("我是男人的行为:吃");
}
}
抽象类、密封类、抽象方法和虚方法
class Program
{
static void Main(string[] args)
{
Man man = new Man();
man.Eat();
man.Say();
}
}
public abstract class People
{
//注意:如果类中有抽象方法,则类必须声明为抽象类。
public People()
{
Console.WriteLine("父类人");
}
public abstract void Eat();
//有时候不想把类声明为抽象类,但又想实现方法在基类里不具体实现,
//而是想实现方法由派生类重写。遇到这种情况时可使用virtual关键字将方法声明为虚方法
public virtual void Say()
{
//注意虚方法必须声明方法主体,抽象方法则不需要
Console.WriteLine("父类的虚方法");
}
}
class Man:People
{
public Man()
{
Console.WriteLine("子类男人");
}
public override void Eat()
{
Console.WriteLine("我是男人的行为:吃");
}
public override void Say()
{
Console.WriteLine("子类的Say方法");
}
}
有参数的构造函数
class Program
{
static void Main(string[] args)
{
Man man = new Man("构造函数");
//结果仍然是先输出父类构造函数,然后再输出子类构造函数
}
}
public class People
{
public People(string s)
{
Console.WriteLine("父类"+s);
}
}
class Man:People
{
//在继承时,如果基类构造函数是有参数的,子类构造函数也必须有一个有参数的构造函数,否则会报错
//派生类构造函数中的参数是一个形参,base()方法中的参数是实参,通过base()方法传输基类参数的值
//base()方法中实参名要与形参名对应
public Man(string s):base(s)
{
Console.WriteLine("子类构造函数");
}
}
例子:
动物为基类
猫、狗继承动物
波斯猫继承猫
哈士奇继承狗
波斯猫继承猫
动物类
class DongWu
{
private string name;
private string color;
private string food;
private string run;
public DongWu( string name,string color,string food)
{
this.name = name;
this.color = color;
this.food = food;
Console.WriteLine("动物");
}
public void Run()
{
Console.WriteLine("会跑");
}
public string Name
{
get{ return name; }
set { this.name = value; }
}
public string Color
{
get { return color; }
set { this.color = value; }
}
public string Food
{
get { return food; }
set { this.food = value; }
}
}
狗类继承动物类
class Dog:DongWu
{
private string js;
public Dog(string name,string color,string food) :base(name,color,food)
{
Console.WriteLine("狗");
}
public void Js()
{
Console.WriteLine("叫声是汪汪");
}
}
猫类继承动物类
class Cat:DongWu
{
public Cat(string name,string color,string food) : base(name, color, food)
{
Console.WriteLine("猫");
}
}
哈士奇继承狗类
class Hsq:Dog
{
public Hsq(string name,string color,string food) : base(name, color, food)
{
Console.WriteLine("是" + name + ",毛色是" + color + ",食物是" + food);
}
}
波斯猫继承猫类
class Bsm:Cat
{
public Bsm(string name,string color,string food) : base(name, color, food)
{
Console.WriteLine("是" + name + ",毛色是" + color + ",食物是" + food);
}
}
只调用哈士奇和波斯猫
Hsq hsq = new Hsq("哈士奇", "黑白相间", "骨头");
hsq.Run();
hsq.Js();
Bsm bsm = new Bsm("波斯猫","白色","鱼");
bsm.Run();
Console.ReadKey();
结果如下