继承是面向对象编程(OOP)的核心概念之一,它允许我们创建一个新的类,该类从现有的类继承成员。通过继承,子类可以重用、扩展和修改父类的行为,从而提高代码的复用性和可维护性。C#中的继承使得代码更加模块化和组织化。
1. 继承的基本概念
在C#中,继承使用:
符号表示。一个类只能继承一个直接父类(单继承),但可以实现多个接口。
示例:
public class Animal
{
public void Eat()
{
Console.WriteLine("Eating...");
}
}
public class Dog : Animal
{
public void Bark()
{
Console.WriteLine("Barking...");
}
}
class Program
{
static void Main(string[] args)
{
Dog dog = new Dog();
dog.Eat(); // 基类方法
dog.Bark(); // 派生类方法
}
}
在这个示例中,Dog
类继承自Animal
类,从而获得了Animal
类的Eat
方法,并添加了自己的Bark
方法。
2. 重写基类方法
在子类中可以使用override
关键字重写基类中的虚方法。基类中的方法需要使用virtual
关键字标识为虚方法。
示例:
public class Animal
{
public virtual void MakeSound()
{
Console.WriteLine("Some generic animal sound");
}
}
public class Dog : Animal
{
public override void MakeSound()
{
Console.WriteLine("Bark");
}
}
class Program
{
static void Main(string[] args)
{
Animal myAnimal = new Animal();
myAnimal.MakeSound(); // 输出 Some generic animal sound
Dog myDog = new Dog();
myDog.MakeSound(); // 输出 Bark
Animal anotherDog = new Dog();
anotherDog.MakeSound(); // 输出 Bark
}
}
在这个示例中,Dog
类重写了Animal
类的MakeSound
方法,展示了多态性。
3. 基类构造函数
子类构造函数可以调用基类构造函数,以确保基类的部分正确初始化。可以使用base
关键字调用基类的构造函数。
示例:
public class Animal
{
public string Name { get; set; }
public Animal(string name)
{
Name = name;
}
}
public class Dog : Animal
{
public Dog(string name) : base(name)
{
}
public void Display()
{
Console.WriteLine($"Dog's name is: {Name}");
}
}
class Program
{
static void Main(string[] args)
{
Dog dog = new Dog("Buddy");
dog.Display(); // 输出 Dog's name is: Buddy
}
}
在这个示例中,Dog
类的构造函数调用了基类Animal
的构造函数,并传递了参数。
4. 密封类和密封方法
在C#中,可以使用sealed
关键字阻止类被继承,或者阻止方法在派生类中被重写。
密封类:
public sealed class Animal
{
public void MakeSound()
{
Console.WriteLine("Some sound");
}
}
// 下面的代码将导致编译错误,因为Animal类是密封的
// public class Dog : Animal
// {
// }
密封方法:
public class Animal
{
public virtual void MakeSound()
{
Console.WriteLine("Some sound");
}
}
public class Dog : Animal
{
public sealed override void MakeSound()
{
Console.WriteLine("Bark");
}
}
// 下面的代码将导致编译错误,因为MakeSound方法是密封的
// public class Bulldog : Dog
// {
// public override void MakeSound()
// {
// Console.WriteLine("Woof");
// }
// }
在这些示例中,密封类不能被继承,密封方法不能被重写。
5. 抽象类
抽象类是不能实例化的类,它只能作为其他类的基类。抽象类可以包含抽象方法,这些方法必须在派生类中实现。抽象类使用abstract
关键字定义。
示例:
public abstract class Animal
{
public abstract void MakeSound();
public void Sleep()
{
Console.WriteLine("Sleeping...");
}
}
public class Dog : Animal
{
public override void MakeSound()
{
Console.WriteLine("Bark");
}
}
class Program
{
static void Main(string[] args)
{
// Animal myAnimal = new Animal(); // 这将导致编译错误,因为Animal是抽象类
Dog myDog = new Dog();
myDog.MakeSound(); // 输出 Bark
myDog.Sleep(); // 输出 Sleeping...
}
}
在这个示例中,Animal
类是一个抽象类,包含一个抽象方法MakeSound
和一个具体方法Sleep
。Dog
类继承自Animal
类,并实现了MakeSound
方法。
6. 接口与继承
一个类可以实现多个接口,而一个类只能继承一个基类。接口定义了一组方法和属性的契约,实现接口的类必须实现接口中的所有成员。
示例:
public interface IFlyable
{
void Fly();
}
public interface IRunnable
{
void Run();
}
public class Bird : IFlyable, IRunnable
{
public void Fly()
{
Console.WriteLine("Flying...");
}
public void Run()
{
Console.WriteLine("Running...");
}
}
class Program
{
static void Main(string[] args)
{
Bird bird = new Bird();
bird.Fly(); // 输出 Flying...
bird.Run(); // 输出 Running...
}
}
在这个示例中,Bird
类实现了IFlyable
和IRunnable
接口,并实现了接口中的所有方法。
7. 接口的继承
接口也可以继承其他接口,这使得接口更具可重用性和灵活性。
示例:
public interface IAnimal
{
void Eat();
}
public interface IFlyable : IAnimal
{
void Fly();
}
public class Bird : IFlyable
{
public void Eat()
{
Console.WriteLine("Eating...");
}
public void Fly()
{
Console.WriteLine("Flying...");
}
}
class Program
{
static void Main(string[] args)
{
Bird bird = new Bird();
bird.Eat(); // 输出 Eating...
bird.Fly(); // 输出 Flying...
}
}
在这个示例中,IFlyable
接口继承了IAnimal
接口,Bird
类实现了IFlyable
接口,并实现了所有继承的成员。
结束语
C#中的继承概念,包括类的继承、方法重写、基类构造函数、密封类和方法、抽象类、接口与继承、以及接口的继承。继承使得代码更加模块化和组织化,有助于代码的复用和维护。