一、继承的概念
1. 若类A继承类B:
那么类A将会继承类B的所有成员,类A将拥有类B的所有特征和行为。
2. 被继承的类:称为父类、基类、超类
3. 继承的类:称为子类、派生类
4. 子类可以拥有自己的特征和行为
5. 特点:
(1)单根性:一个子类只能有一个父类
(2)传递性:子类可以间接继承父类的父类
二、基本语法
语法:class 子类名 : 父类名
1. 创建父类
using System;
namespace Extends
{
class Animal // 定义一个父类Animal
{
public string Name { get; set; } // 父类属性Name
public virtual void Speak() // 父类方法Speak
{
Console.WriteLine("Animal speak");
}
}
}
2. 创建子类
using System;
namespace Extends
{
class Animal // 定义一个父类Animal
{
public string Name { get; set; } // 基类属性Name
public void Speak() // 基类方法Speak
{
Console.WriteLine("Animal speak");
}
}
class Bird : Animal // 定义一个子类Bird,继承自Animal类
{
public void Speak() // 重写基类方法Speak
{
Console.WriteLine("Bird chirp");
}
public void Fly() // Bird类特有方法Fly
{
Console.WriteLine("Bird fly");
}
}
}
3. 使用子类
using System;
namespace Extends
{
class Program
{
static void Main(string[] args)
{
Bird b = new Bird(); // 创建Bird类的对象
b.Name = "Sparrow"; // 设置Bird对象的Name属性:不在Bird类中定义,但可以访问父类Animal的属性
b.Speak(); // 调用Bird类的Speak方法
b.Fly(); // 调用Bird类的Fly方法
}
}
class Animal // 定义一个父类Animal
{
public string Name { get; set; } // 基类属性Name
public void Speak() // 基类方法Speak
{
Console.WriteLine("Animal speak");
}
}
class Bird : Animal // 定义一个子类Bird,继承自Animal类
{
public void Speak() // 重写基类方法Speak
{
Console.WriteLine("Bird chirp");
}
public void Fly() // Bird类特有方法Fly
{
Console.WriteLine("Bird fly");
}
}
}
三、访问修饰符
1. public(公开的):类内部、子类、类外部都能访问
2. protected(保护的):类内部和子类能访问,类外部不能访问
3. private(私有的):只有类内部能访问,子类和类外部都不能访问
4. 测试:
using System;
namespace Extends
{
class Program
{
static void Main(string[] args)
{
Bird b = new Bird(); // 创建Bird类的对象
b.Name = "Sparrow"; // 设置Bird对象的Name属性:不在Bird类中定义,但可以访问父类Animal的属性
b.Speak(); // 调用Bird类的Speak方法
b.Fly(); // 调用Bird类的Fly方法
Animal a = new Animal(); // 创建Animal类的对象
a.Name = "小白"; // 可以访问Animal类的公共属性Name
// a.Age = 3; // 编译错误:无法访问Animal类的受保护属性Age
// a.IsAlive = true; // 编译错误:无法访问Animal类的私有属性IsAlive
}
}
class Animal // 定义一个父类Animal
{
public string Name { get; set; } // 父类属性Name
protected int Age { get; set; } // 父类受保护属性Age
private bool IsAlive { get; set; } // 父类私有属性IsAlive
public void Speak() // 基类方法Speak
{
Console.WriteLine("Animal speak");
}
public void Test()
{
Name = "Test"; // 可以在Animal类内部访问公共属性Name
Age = 5; // 可以在Animal类内部访问受保护属性Age
IsAlive = true; // 可以在Animal类内部访问私有属性IsAlive
}
}
class Bird : Animal // 定义一个子类Bird,继承自Animal类
{
public void Speak() // 重写基类方法Speak
{
Console.WriteLine("Bird chirp");
}
public void Fly() // Bird类特有方法Fly
{
Console.WriteLine("Bird fly");
}
public void Test()
{
Name = "Test"; // 可以访问父类的公共属性Name
Age = 5; // 子类可以访问父类的受保护属性Age
// IsAlive = true; // 编译错误:无法访问私有属性IsAlive
}
}
}
四、子类和父类的同名成员
若子类有和父类同名的成员变量,则会覆盖父类的该成员。
但是极不建议使用。
关于多态的用法,我们之后再学习。
五、继承中的构造函数
1. 特点:当声明一个子类对象时,先执行父类的构造函数,再执行子类的构造函数
2. 注意:
(1)若类中没有声明构造方法,会默认提供一个无参的构造方法
(2)子类调用父类的构造方法时,默认调用的是父类的无参构造方法
3. 测试:
using System;
namespace Extends
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("创建Bird对象:");
Bird b = new Bird(); // 创建Bird类的对象
b.Name = "Sparrow"; // 设置Bird对象的Name属性:不在Bird类中定义,但可以访问父类Animal的属性
b.Speak(); // 调用Bird类的Speak方法
b.Fly(); // 调用Bird类的Fly方法
Console.WriteLine("创建Animal对象:");
Animal a = new Animal(); // 创建Animal类的对象
a.Name = "小白"; // 可以访问Animal类的公共属性Name
// a.Age = 3; // 编译错误:无法访问Animal类的受保护属性Age
// a.IsAlive = true; // 编译错误:无法访问Animal类的私有属性IsAlive
}
}
class Animal // 定义一个父类Animal
{
public string Name { get; set; } // 父类属性Name
protected int Age { get; set; } // 父类受保护属性Age
private bool IsAlive { get; set; } // 父类私有属性IsAlive
public Animal() // 构造函数
{
Console.WriteLine("调用父类构造方法");
}
public void Speak() // 基类方法Speak
{
Console.WriteLine("Animal speak");
}
public void Test()
{
Name = "Test"; // 可以在Animal类内部访问公共属性Name
Age = 5; // 可以在Animal类内部访问受保护属性Age
IsAlive = true; // 可以在Animal类内部访问私有属性IsAlive
}
}
class Bird : Animal // 定义一个子类Bird,继承自Animal类
{
public Bird() // 构造函数
{
Console.WriteLine("调用子类构造方法");
}
public void Speak() // 重写基类方法Speak
{
Console.WriteLine("Bird chirp");
}
public void Fly() // Bird类特有方法Fly
{
Console.WriteLine("Bird fly");
}
public void Test()
{
Name = "Test"; // 可以访问父类的公共属性Name
Age = 5; // 子类可以访问父类的受保护属性Age
// IsAlive = true; // 编译错误:无法访问私有属性IsAlive
}
}
}
运行结果如下:
六、base关键字
1. 与this()类似,他的作用是调用父类的构造方法
2. 使用:
using System;
namespace Extends
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("创建Bird对象:");
Bird b = new Bird(); // 创建Bird类的对象
b.Name = "Sparrow"; // 设置Bird对象的Name属性:不在Bird类中定义,但可以访问父类Animal的属性
b.Speak(); // 调用Bird类的Speak方法
b.Fly(); // 调用Bird类的Fly方法
Console.WriteLine("创建Animal对象:");
Animal a = new Animal(); // 创建Animal类的对象
a.Name = "小白"; // 可以访问Animal类的公共属性Name
// a.Age = 3; // 编译错误:无法访问Animal类的受保护属性Age
// a.IsAlive = true; // 编译错误:无法访问Animal类的私有属性IsAlive
Console.WriteLine("构造方法调用顺序测试:");
Bird b2 = new Bird("莺莺", 1);
}
}
class Animal // 定义一个父类Animal
{
public string Name { get; set; } // 父类属性Name
protected int Age { get; set; } // 父类受保护属性Age
private bool IsAlive { get; set; } // 父类私有属性IsAlive
public Animal() // 构造函数
{
Console.WriteLine("调用父类无参构造方法");
}
public Animal(string name) // 带参数的构造函数
{
Name = name; // 设置Name属性
Console.WriteLine("调用父类带一个参数的构造方法");
}
public void Speak() // 基类方法Speak
{
Console.WriteLine("Animal speak");
}
public void Test()
{
Name = "Test"; // 可以在Animal类内部访问公共属性Name
Age = 5; // 可以在Animal类内部访问受保护属性Age
IsAlive = true; // 可以在Animal类内部访问私有属性IsAlive
}
}
class Bird : Animal // 定义一个子类Bird,继承自Animal类
{
public Bird() // 构造函数
{
Console.WriteLine("调用子类无参构造方法");
}
public Bird(string name) : base(name) // 带参数的构造函数,调用父类构造函数
{
Console.WriteLine("调用子类带一个参数的构造方法");
}
public Bird(string name, int age) : this(name) // 带两个参数的构造函数,调用父类构造函数
{
Age = age; // 设置受保护属性Age
Console.WriteLine("调用子类带两个参数的构造方法");
}
public void Speak() // 重写基类方法Speak
{
Console.WriteLine("Bird chirp");
}
public void Fly() // Bird类特有方法Fly
{
Console.WriteLine("Bird fly");
}
public void Test()
{
Name = "Test"; // 可以访问父类的公共属性Name
Age = 5; // 子类可以访问父类的受保护属性Age
// IsAlive = true; // 编译错误:无法访问私有属性IsAlive
}
}
}
运行结果如下:
至此,面向对象的三大特性之一:继承就学习完了。
今天的学习就到这里了。感谢阅读。
再见!