先定义了一个基类Animal
,以及一个继承自Animal
的子类Dog
。子类Dog
重写了父类Animal
中的MakeSound
方法,并添加了自己的Bark
方法。在Main
方法中,我们创建了基类和子类的实例,并调用了它们的方法。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp6
{
// 父类 Animal
class Animal
{
protected string name; // 受保护字段 name
// 构造函数,用于初始化 name 字段
public Animal(string name)
{
this.name = name;
}
// 虚方法,可以在子类中被重写
public virtual void MakeSound()
{
Console.WriteLine("The animal makes a sound.");
// 触发事件
SoundMade?.Invoke(this, EventArgs.Empty);
}
// 声明事件
public event EventHandler SoundMade;
}
// 子类 Dog,继承自 Animal
class Dog : Animal
{
// 子类构造函数,调用父类的构造函数来初始化 name 字段
public Dog(string name) : base(name)
{
}
// 子类特有的方法,用于输出狗叫声
public void Bark()
{
Console.WriteLine("The dog barks.");
}
// 重写父类的虚方法
public override void MakeSound()
{
Console.WriteLine("The dog makes a sound.");
base.MakeSound(); // 调用父类的 MakeSound 方法,由父类负责触发事件
}
}
internal class Program
{
static void Main(string[] args)
{
// 创建父类对象并调用其方法
Animal animal = new Animal("Animal");
animal.MakeSound(); // 输出:"The animal makes a sound."
// 创建子类对象并调用其方法
Dog dog = new Dog("Dog");
dog.MakeSound(); // 输出:"The dog makes a sound."
dog.Bark(); // 输出:"The dog barks."
// 使用父类引用指向子类对象,并调用其方法
Animal dog2 = new Dog("Dog2");
dog2.MakeSound(); // 输出:"The dog makes a sound."
// dog2.Bark(); // 错误!父类引用不能调用子类特有的方法
Console.ReadKey();
}
}
}
以下是一些关键概念和语法规则:
-
继承关键字:
- 使用
:
符号在子类的类定义中指定基类。例如:class ChildClass : ParentClass
。
- 使用
-
访问修饰符:
- 可以使用
public
、protected
、private
和internal
等访问修饰符来控制继承成员的可见性。
- 可以使用
-
基类成员的访问:
- 子类可以通过父类的实例来访问父类的成员(如果成员的访问修饰符允许访问)。
- 也可以使用关键字
base
在子类中显式地引用父类的成员。 - 父类中的私有成员对子类不可见。
-
方法重写:
- 子类可以通过在子类中重新定义与父类中具有相同名称和签名的方法来重写父类的方法。
- 使用
override
关键字标记要重写的方法。 - 重写方法必须使用与父类方法相同的返回类型,并且在复写方法中可以使用
base
关键字调用父类的实现。 - 在子类中重写父类的方法时同时触发事件, 应该调用父类的base.方法,而不是直接调用事件,因为在子类中直接调用父类的事件是不允许的。如果子类重写了父类的虚方法,并在其中触发了父类的事件,那么在调用子类的方法时,既会触发子类的事件处理程序,也会触发父类的事件处理程序。这可能会导致意外的行为,应该避免这种情况。
-
构造函数:
- 子类可以定义自己的构造函数,但可以使用
base
关键字调用父类的构造函数来初始化继承的成员。
- 子类可以定义自己的构造函数,但可以使用
总结:C#中的类继承是一种重要的面向对象编程概念,可以通过继承一个类(称为子类或派生类)来扩展另一个类(称为父类或基类)的功能。继承允许子类继承父类的属性、方法和其他成员,并且可以添加自己的额外成员或覆盖父类的成员。