【C#零基础从入门到精通】(二十五)——C#三大特性-继承详解

【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 自动拥有了 ParentClassParentProperty 属性和 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."
    }
}

在上述代码中,DogCat 类继承自 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 间接继承了 GrandParentClassGrandParentMethod 方法。

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

当父类的方法被声明为 virtualabstract 时,子类可以使用 override 关键字重写该方法,以提供不同的实现。例如前面提到的 AnimalDogCat 类的例子。

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"
    }
}

在上述代码中,ChildClassSomeMethod 方法使用 new 关键字隐藏了 ParentClassSomeMethod 方法。当通过 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 类实现了 IParent1IParent2 两个接口,从而获得了这两个接口所定义的方法,实现了功能的组合,类似于多继承。

综上所述,继承是 C# 中非常重要的特性,它可以提高代码的复用性和可维护性,同时为多态性等高级特性提供基础。在使用继承时,需要注意访问修饰符、构造函数的调用、方法重写和隐藏等方面的问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_Csharp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值