C#的继承和多态

面向对象核心概念详解

继承

继承是面向对象程序设计中最重要的核心概念之一。继承允许我们根据一个类来定义另一个类。

当创建一个类时,不需要完全重新编写新的数据成员和函数成员,只需要设计一个新类,继承了已有类的成员即可。这个已有类为基类(父类),这个新类为派生类(子类)

继承的思想实现了属于关系,如狗属于哺乳动物,哺乳动物属于动物,因此狗属于动物

C#不支持多重继承,但支持接口的多重继承,一个类可以实现多个接口。换句话来说一个类可以继承多个接口,但只能继承自一个类

1. 语法实现继承下·

csharp 复制代码
namespace ConsoleApp1
{
        //基类 Animal
    class Animal
    {
        public string? Name { get; set; }
        public void Eat() 
        {
            Console.WriteLine($"{Name} is Eating...");
        }
    }
    //派生类
    class Dog : Animal 
    {
        public void Bark() 
        {
            Console.WriteLine($"{Name} is Barking...");
        }
    }
    internal class Program
    {
        static void Main(string[] args)
        {
            Dog dog1 = new Dog();
            dog1.Name = "小黄";//继承自Animal
            dog1.Eat();//调用基类方法
            dog1.Bark();//调用派生类方法
        }
    }
}

关键特性

  • 单继承: C#只支持单继承(一个类只能继承一个基类)
  • 传递性: 继承关系可以传递(Dog=>Animal=>Object)
  • 成员继承:派生类自动获取基类的非私有成员
  • 构造函数要求:派生类必须调用用基类的构造函数(显示或隐式)

2. base关键字

csharp 复制代码
我们可以使用base关键字调用基类的构造函数和方法
csharp 复制代码
namespace ConsoleApp1
{
        //基类 Animal
    class Animal
    {
        public string? Name { get; set; }
        public int Age { get; set; }
        public void Eat() 
        {
            Console.WriteLine($"{Name} is Eating...");
        }
        public Animal(string nameV,int ageV) 
        {
            Name = nameV;
            Age = ageV;
            Console.WriteLine("Animal对象已被创建 动物的名字是{0},它有{1}岁了",Name,Age);
        }
    }
    //派生类
    class Dog : Animal 
    {
        public void Bark() 
        {
            Console.WriteLine($"{Name} is Barking...");
        }

        //通过:base调用基类的构造函数并传递name和age参数对基类初始化
        public Dog(string name  , int age):base(name,age) { }

        //通过base关键字调用基类的方法,也可以省略base
        public void Met() 
        {
            //base.Eat();
            //省略base
            Eat();
        }
    }
    internal class Program
    {
        static void Main(string[] args)
        {
            Dog dog1 = new Dog("小黄",7);
            dog1.Met();
            
        }
    }
}

三种主要用法

  1. 调用基类构造函数给基类初始化 :base(参数)
  2. 访问基类成员 base.成员名
  3. 解决命名冲突

重要限制

  • 必须在构造函数首行使用
  • 不能同时使用this()和base()
  • 静态方法中不能使用base

virtual和override关键字重写

方法重写机制

arduino 复制代码
namespace ConsoleApp1
{
    class Shap 
    {
        //通过virtual关键字定义一个虚方法 可被重写
        public virtual double CalculateArea() 
        {
            return 0;
        }
    }
    class Circle : Shap 
    {
        public double Radius { get; set; }
        //通过override关键字重写CalculateArea方法
        public override double CalculateArea()
        {
            return Math.PI*Radius*Radius;
        }
    }

    class Rectangle : Shap 
    {
        public double width { get; set; }
        public double height { get; set; }
        //通过override关键字重写CalculateArea方法
        public override double CalculateArea()
        {
            return width*height;
        }
    }
    internal class Program
    {
        static void Main(string[] args)
        {
            Circle c = new Circle();//实现多态
            c.Radius = 10d;
            Rectangle Rect = new Rectangle();//实现多态
            Rect.width = 5;
            Rect.height = 6;

            Console.WriteLine(c.CalculateArea());
            Console.WriteLine(Rect.CalculateArea());


        }
    }
}

关键规则

关键字​ ​位置​ ​作用​ ​是否必须​
virtual 基类 声明方法可被重写 可选
override 派生类 提供新实现 重写时必须
new 派生类 隐藏基类方法 可选(不推荐)

重写vs隐藏

new 关键字可以隐藏基类中的同名成员,此时基类的方法被隐藏你所调用的是派生类的方法(非多态)。也就是说使用new关键字修饰成员后会隐藏同名的基类成员,此时调用的同名成员是派生类的成员而不是基类的成员

csharp 复制代码
namespace ConsoleApp1
{
    class Shap 
    {
        //通过virtual关键字定义一个虚方法 可被重写
        public virtual double CalculateArea() 
        {
            return 0;
        }
    }
    class Triangle : Shap 
    {
        public new double CalculateArea() 
        {
            return 1;
        }
    }
  
    internal class Program
    {
        static void Main(string[] args)
        {
            Triangle Tr = new Triangle();
            Console.WriteLine(Tr.CalculateArea());//打印1
        }
    }
}

多态的概念与好处

核心概念

多态:同一操作作用于不同类的实例,产生不同的执行结果。也就是说同一操作在不同类的使用情境下会产生不同的结果

三种实现方式

  1. 继承多态:通过虚方法重写实现
  2. 接口多态:通过接口实现
  3. 参数多态:泛型编程
csharp 复制代码
public class GraphicsRenderer
{
    // 多态方法:可处理任何Shape派生类
    public void Render(Shape shape)
    {
        double area = shape.CalculateArea(); // 多态调用
        Console.WriteLine($"Rendering shape with area: {area}");
    }
}

// 使用
var renderer = new GraphicsRenderer();
renderer.Render(new Circle(5));    // 输出圆面积
renderer.Render(new Rectangle(3,4)); // 输出矩形面积

总结:结成体系的核心价值

相关推荐
薄荷撞~可乐4 小时前
C#高并发与并行理解处理
开发语言·c#
sali-tec4 小时前
C# 基于halcon的视觉工作流-章33-矩状测量
开发语言·人工智能·算法·计算机视觉·c#
王维志5 小时前
Unity Embedded Browser文档翻译
unity·c#
FlYFlOWERANDLEAF5 小时前
DevExpress中Word Processing Document API学习记录
学习·c#·word
棉晗榜5 小时前
C#写字符串到Modbus中
c#·modbus
Hello.Reader15 小时前
从零到一上手 Protocol Buffers用 C# 打造可演进的通讯录
java·linux·c#
浪扼飞舟16 小时前
c#基础(一)
开发语言·c#
一个帅气昵称啊17 小时前
C# .NET EFCore 性能优化
性能优化·c#·.net
ArabySide18 小时前
【C#】理解.NET内存机制:堆、栈与装箱拆箱的底层逻辑及优化技巧
c#