--继承:子类实例化的时候,父类构造函数也会跟随执行
继承:属于面向对象三大特性之一(封装,继承,多态)
/*
* 父类中抽离"公共成员"
* 子类中"扩展"特殊的成员
*
* 基类:父类 Animal
* 派生类:子类 Dog
*
* 继承的核心思想:子类使用父类公开的属性和方法,同时拓展自己的特性
*/
先定义一个Animal类,之后用Dog类继承Animal类
//调用了无参的构造函数
Animal laohu = new Animal();
laohu.Name = "老虎";
//调用了带有参数的构造函数
Animal daxiang = new Animal(1, "大象");
//laohu和daxiang都属于Animal的实例,拥有独立的内存空间
Console.WriteLine(laohu.Name);
Console.WriteLine(daxiang.Name);
//实例化的同时进行初始化
Animal houzi = new Animal() { Id = 2, Name = "猴子" };
Console.WriteLine(houzi.Name);
public class Animal
{
public int Id
{
get;
set;
}
public string Name
{
get;
set;
}
//构造函数
public Animal()
{
Console.WriteLine("构造函数中实例化时调用,无参构造函数");
}
//构造函数,可以携带参数,一般都是公开的,没有返回值,函数名称和类名一样
//与上面的Anmial都成为构造函数,构造函数可以有多个,名字相同,参数上有变化
public Animal(int id, string name)
{
this.Id = id;
this.Name = name;
Console.WriteLine("这属于有参构造函数");
}
//virtual:虚方法,表示占用一个位置,子类继承之后想用就用,不想用允许重写(替换掉)
public virtual void Eat(string food)
{
Console.WriteLine($"{food}");
}
}
Dog dog = new Dog();
思考:为什么Dog中什么都没声明,但是却能使用Id,和Name这两个属性?
答:因为Dog继承自Animal,所以在使用时可以使用Animal中公开的属性和方法
dog.Id = 3;
dog.Name = "小黄";
//父类公开的方法也可以继承
dog.Eat("骨头");
继承 语法结构子类:父类,类之间支持单继承(单向)
该类的继承链是:Object--->>>Animal--->>>Dog
在C#中最顶级的基类是object,所有的类都继承自Object
public class Dog:Animal
{
public int Age;
public Dog()
{
Console.WriteLine("子类Dog的无参构造函数");
}
//推荐的写法
//base()代表父类的构造函数,加上参数就是访问父类的有参构造函数
public Dog(int id, string name, int age) : base(id, name)
{
this.Age = age;
}
//这里需要注意,和父类中公开的被用作继承的方法重名了,会覆盖掉父类中的方法,转而调用自身的
//override: 重写父类的虚方法,把父类继承过来的Eat替换掉, 名称保留,业务逻辑重写
public override void Eat(string food)
{
Console.WriteLine($"{this.Name}喜欢吃:{food}");
}
如果要使用父类中的方法,不考虑在子类中重写,那么直接调用父类的方法即可.
如果打算在父类的方法上完全推到逻辑重新来整理,又不想换名字,那么可以考虑把父类方法重写,父类方法(virtual),子类使用override
调用带有参数的构造函数时,无参构造函数也会先执行.
Dog d2 = new Dog(4,"小黑",2);
//这里的4,和小黑都通过构造函数中的base传递给了父类,让父类构造函数赋值,子类只是纯粹的调用者