【C#零基础从入门到精通】(二十五)——C#三大特性-继承详解
在 C# 中,继承是面向对象编程的一个重要特性,它允许一个类(子类或派生类)继承另一个类(父类或基类)的属性和方法,从而实现代码的复用和扩展。以下是关于 C# 继承的详细介绍:
1. 继承的基本概念和语法
继承通过在子类的类名后使用冒号 :
并指定父类的名称来实现。其基本语法如下:
// 定义父类
class ParentClass
{
public string ParentProperty { get; set; }
public void ParentMethod()
{
Console.WriteLine("This is a method in the parent class.");
}
}
// 定义子类,继承自 ParentClass
class ChildClass : ParentClass
{
public string ChildProperty { get; set; }
public void ChildMethod()
{
Console.WriteLine("This is a method in the child class.");
}
}
在上述代码中,ChildClass
继承自 ParentClass
,这意味着 ChildClass
自动拥有了 ParentClass
的 ParentProperty
属性和 ParentMethod
方法,同时还可以定义自己的属性(ChildProperty
)和方法(ChildMethod
)。
2. 继承的特性
2.1 代码复用
继承最主要的好处之一是实现代码复用。子类可以直接使用父类中定义的属性和方法,避免了重复编写相同的代码。例如:
class Program
{
static void Main()
{
ChildClass child = new ChildClass();
// 可以访问父类的属性
child.ParentProperty = "Value from parent";
// 可以调用父类的方法
child.ParentMethod();
// 可以访问子类自己的属性和方法
child.ChildProperty = "Value from child";
child.ChildMethod();
}
}
2.2 多态性基础
继承为多态性提供了基础。多态性允许不同的对象对同一消息做出不同的响应。通过继承和方法重写,可以实现运行时的多态性。例如:
class Animal
{
public virtual void MakeSound()
{
Console.WriteLine("The animal makes a sound.");
}
}
class Dog : Animal
{
public override void MakeSound()
{
Console.WriteLine("The dog barks.");
}
}
class Cat : Animal
{
public override void MakeSound()
{
Console.WriteLine("The cat meows.");
}
}
class Program
{
static void Main()
{
Animal animal1 = new Dog();
Animal animal2 = new Cat();
animal1.MakeSound(); // 输出 "The dog barks."
animal2.MakeSound(); // 输出 "The cat meows."
}
}
在上述代码中,Dog
和 Cat
类继承自 Animal
类,并重写了 MakeSound
方法。当通过 Animal
类型的引用调用 MakeSound
方法时,实际执行的是对象所属类重写后的方法,这就是多态性的体现。
2.3 单继承
C# 只支持单继承,即一个类只能直接继承自一个父类。但是一个类可以间接继承自多个类,例如通过多层继承的方式。例如:
class GrandParentClass
{
public void GrandParentMethod()
{
Console.WriteLine("This is a method in the grandparent class.");
}
}
class ParentClass : GrandParentClass
{
public void ParentMethod()
{
Console.WriteLine("This is a method in the parent class.");
}
}
class ChildClass : ParentClass
{
public void ChildMethod()
{
Console.WriteLine("This is a method in the child class.");
}
}
在这个例子中,ChildClass
间接继承了 GrandParentClass
的 GrandParentMethod
方法。
3. 访问修饰符与继承
在继承中,访问修饰符决定了子类对父类成员的访问权限:
public
:父类的public
成员可以在子类和任何其他类中访问。private
:父类的private
成员只能在父类内部访问,子类无法直接访问。protected
:父类的protected
成员可以在父类内部和子类中访问,但在其他类中无法访问。internal
:父类的internal
成员可以在同一个程序集内的子类中访问。protected internal
:父类的protected internal
成员可以在同一个程序集内的任何类以及不同程序集的子类中访问。
4. 构造函数与继承
子类的构造函数在创建对象时会默认调用父类的无参构造函数。如果父类没有无参构造函数,子类的构造函数需要使用 base
关键字显式调用父类的有参构造函数。例如:
class ParentClass
{
public ParentClass(int value)
{
Console.WriteLine($"Parent class constructor with value: {value}");
}
}
class ChildClass : ParentClass
{
public ChildClass(int value) : base(value)
{
Console.WriteLine($"Child class constructor with value: {value}");
}
}
class Program
{
static void Main()
{
ChildClass child = new ChildClass(10);
}
}
在上述代码中,ChildClass
的构造函数使用 base(value)
显式调用了 ParentClass
的有参构造函数。
5. 方法重写和隐藏
5.1 方法重写(override
)
当父类的方法被声明为 virtual
或 abstract
时,子类可以使用 override
关键字重写该方法,以提供不同的实现。例如前面提到的 Animal
、Dog
和 Cat
类的例子。
5.2 方法隐藏(new
)
如果子类定义了一个与父类方法签名相同的方法,但没有使用 override
关键字,而是使用 new
关键字,那么这个方法会隐藏父类的方法。例如:
class ParentClass
{
public void SomeMethod()
{
Console.WriteLine("Parent class method");
}
}
class ChildClass : ParentClass
{
public new void SomeMethod()
{
Console.WriteLine("Child class method");
}
}
class Program
{
static void Main()
{
ParentClass parent = new ParentClass();
parent.SomeMethod(); // 输出 "Parent class method"
ChildClass child = new ChildClass();
child.SomeMethod(); // 输出 "Child class method"
ParentClass parentAsChild = new ChildClass();
parentAsChild.SomeMethod(); // 输出 "Parent class method"
}
}
在上述代码中,ChildClass
的 SomeMethod
方法使用 new
关键字隐藏了 ParentClass
的 SomeMethod
方法。当通过 ParentClass
类型的引用调用 SomeMethod
时,执行的是父类的方法。
6.实现类似多继承功能的替代方案
1. 接口实现
接口在 C# 中是一种只包含方法签名(没有方法体)的抽象类型。一个类可以实现多个接口,这在一定程度上能实现类似多继承的效果。
// 定义接口 IParent1
interface IParent1
{
void Method1();
}
// 定义接口 IParent2
interface IParent2
{
void Method2();
}
// 定义类 Child 实现 IParent1 和 IParent2 接口
class Child : IParent1, IParent2
{
public void Method1()
{
Console.WriteLine("Implementation of Method1");
}
public void Method2()
{
Console.WriteLine("Implementation of Method2");
}
}
class Program
{
static void Main()
{
Child child = new Child();
child.Method1();
child.Method2();
}
}
在这个例子中,Child
类实现了 IParent1
和 IParent2
两个接口,从而获得了这两个接口所定义的方法,实现了功能的组合,类似于多继承。
综上所述,继承是 C# 中非常重要的特性,它可以提高代码的复用性和可维护性,同时为多态性等高级特性提供基础。在使用继承时,需要注意访问修饰符、构造函数的调用、方法重写和隐藏等方面的问题