C#中级教程(2)——走进 C# 面向对象编程:从基础到进阶的深度探索

news/2025/2/25 2:50:37

一、为什么选择面向对象编程

        在软件开发的演进过程中,随着程序规模和复杂度的不断增加,传统的编程方式逐渐暴露出局限性。面向对象编程应运而生,它就像是一位智慧的组织者,将程序中的功能进行模块化划分每个模块各司其职,提供特定的功能,而且这些模块相互独立。这种模块化编程极大地提升了代码的可维护性和可扩展性,为开发者带来了诸多便利。例如,在一个电商系统中,用户管理、订单处理、商品展示等功能模块可以各自独立开发、测试和维护,当需要对某个模块进行修改或升级时,不会影响其他模块的正常运行。同时,它还大大增加了代码的重用机会,提高了开发效率,减少了重复劳动。


二、什么是面向对象编程

        面向对象编程(OOP)是一种编程范式,它将现实世界中的事物抽象成程序中的对象。简单来说,OOP 把程序看作是由多个相互协作的对象组成,每个对象都有自己的状态(数据)和行为(方法)。这就好比在一个游戏中,每个角色都有自己的生命值、等级等状态,同时具备攻击、防御、移动等行为。与结构化编程相比,OOP 更符合人类对现实世界的认知方式,使得代码的结构更加清晰、易于理解和维护。


三、类与对象:面向对象的基石

(一)类的定义与结构

        类是创建对象的模板,它定义了对象的属性和行为在 C# 中,类的定义包含访问修饰符、类名、成员变量(数据成员)和成员方法(函数成员)等部分。例如:

public class Employee
{
    // 数据成员(字段)
    private string name;
    private int age;
    private decimal salary;

    // 函数成员(方法)
    public void DisplayInfo()
    {
        Console.WriteLine($"姓名:{name},年龄:{age},薪资:{salary}");
    }

    // 构造函数
    public Employee(string empName, int empAge, decimal empSalary)
    {
        name = empName;
        age = empAge;
        salary = empSalary;
    }
}

        在这个例子中,Employee类定义了员工的基本信息和显示信息的方法。nameagesalary是数据成员,用于存储员工的具体信息;DisplayInfo方法用于展示员工信息;构造函数Employee用于在创建对象时初始化员工的属性。


(二)对象的创建与使用

        对象是类的实例通过new关键字创建

访问权限子类其他包
public
protect
default
private

例如:

Employee emp1 = new Employee("张三", 25, 5000m);
emp1.DisplayInfo();

        上述代码创建了一个Employee类的对象emp1,并调用DisplayInfo方法输出员工信息。创建对象的过程就像是根据图纸(类)制造出一个具体的产品(对象),每个对象都有自己独立的属性值。


四、构造函数:对象的初始化器

        构造函数是一种特殊的方法,用于在创建对象时初始化对象的状态。它与类名相同,没有返回类型。构造函数可以重载,以满足不同的初始化需求。例如:

public class Circle
{
    private double radius;

    // 无参构造函数
    public Circle()
    {
        radius = 1.0;
    }

    // 有参构造函数
    public Circle(double r)
    {
        if (r > 0)
        {
            radius = r;
        }
        else
        {
            radius = 1.0;
        }
    }

    public double CalculateArea()
    {
        return Math.PI * radius * radius;
    }
}

        在Circle类中,定义了无参构造函数和有参构造函数。无参构造函数将圆的半径初始化为 1.0,有参构造函数则根据传入的半径值进行初始化,并对半径进行合法性检查。


五、属性:灵活的数据访问方式

        属性是一种特殊的成员,它提供了对类的字段进行访问的方式,同时可以在访问过程中进行数据验证和其他逻辑处理。属性包含get访问器和set访问器。例如:

public class Person
{
    private int age;

    public int Age
    {
        get
        {
            return age;
        }
        set
        {
            if (value >= 0 && value <= 120)
            {
                age = value;
            }
        }
    }
}

        在Person类中,Age属性对age字段进行了封装。通过get访问器获取age的值,通过set访问器设置age的值,并在设置时进行了年龄范围的验证。

        属性还可以设置为只读或只写,以及使用自动实现属性。例如:

// 只读属性
public string Name { get; private set; }

// 自动实现属性
public int ID { get; set; }

六、匿名类型:便捷的数据定义

         在 C# 中,可以使用var关键字声明匿名类型。匿名类型允许在不定义显式类的情况下创建对象。例如:

var student = new { Name = "李四", Age = 20, Grade = "A" };
Console.WriteLine($"姓名:{student.Name},年龄:{student.Age},成绩:{student.Grade}");

        匿名类型在需要临时创建一个简单对象,且不需要在其他地方复用该类型时非常方便。


七、内存管理:栈与堆的奥秘

        在 C# 中,内存分为栈空间堆空间栈空间较小,但读取速度快,主要用于存储值类型数据和对象的引用。堆空间较大,但读取速度相对较慢,用于存储引用类型的数据。

        值类型(如整数、boolstructchar、小数等)在内存中直接存储其数据值,而引用类型(如string、数组、自定义类等)在内存中需要两段空间,一段存储实际数据(位于堆中),另一段存储指向该数据在堆中位置的引用(位于栈中)。例如:

int num = 10; // num是值类型,存储在栈中
string str = "Hello"; // str是引用类型,"Hello"存储在堆中,str的引用存储在栈中

        C# 的垃圾回收器(GC)会自动管理内存,释放不再使用的对象所占用的内存空间,开发者无需手动管理内存,从而减少了内存泄漏等问题的发生


八、面向对象编程的高级特性

(一)继承:代码复用的利器

        继承是面向对象编程的重要特性之一,它允许一个类从另一个类中获取属性和方法。通过继承,子类可以复用父类的代码,同时还可以添加自己特有的属性和方法。例如:

public class Animal
{
    public string Name { get; set; }

    public void Eat()
    {
        Console.WriteLine($"{Name}正在吃东西。");
    }
}

public class Dog : Animal
{
    public void Bark()
    {
        Console.WriteLine($"{Name}正在汪汪叫。");
    }
}

        在这个例子中,Dog类继承自Animal类,Dog类不仅拥有Animal类的Name属性和Eat方法,还添加了自己的Bark方法。


(二)多态:同一行为的不同表现

        多态是指同一个方法在不同的对象上有不同的表现形式。C# 中实现多态的方式有两种:方法重载方法重写


  1. 方法重载:在同一个类中,定义多个同名但参数列表不同的方法。例如:
public class Calculator
{
    public int Add(int a, int b)
    {
        return a + b;
    }

    public double Add(double a, double b)
    {
        return a + b;
    }
}

Calculator类中,定义了两个Add方法,一个用于整数相加,一个用于双精度浮点数相加。


2. 方法重写:在子类中重新定义父类中已经存在的虚方法。例如:

public class Shape
{
    public virtual double Area()
    {
        return 0;
    }
}

public class Rectangle : Shape
{
    public double Width { get; set; }
    public double Height { get; set; }

    public override double Area()
    {
        return Width * Height;
    }
}

在这个例子中,Rectangle类继承自Shape类,并重写了Area方法,以计算矩形的面积。


(三)接口:定义行为契约

        接口是一种特殊的抽象类型,它定义了一组方法签名,但不包含方法的实现。类可以实现一个或多个接口,以表明它具备某些行为。例如:

public interface IPrintable
{
    void Print();
}

public class Book : IPrintable
{
    public string Title { get; set; }

    public void Print()
    {
        Console.WriteLine($"书名:{Title}");
    }
}

在这个例子中,Book类实现了IPrintable接口,必须实现接口中定义的Print方法。


九、实践案例:开发一个简单的图书馆管理系统

下面通过一个简单的图书馆管理系统案例,综合运用上述所学的面向对象编程知识。

// 定义书籍类
public class Book
{
    public string Title { get; set; }
    public string Author { get; set; }
    public bool IsAvailable { get; set; }

    public Book(string title, string author)
    {
        Title = title;
        Author = author;
        IsAvailable = true;
    }
}

// 定义图书馆类
public class Library
{
    private List<Book> books = new List<Book>();

    public void AddBook(Book book)
    {
        books.Add(book);
        Console.WriteLine($"已添加书籍:{book.Title}");
    }

    public void BorrowBook(string title)
    {
        Book book = books.Find(b => b.Title == title);
        if (book != null && book.IsAvailable)
        {
            book.IsAvailable = false;
            Console.WriteLine($"已借阅书籍:{book.Title}");
        }
        else
        {
            Console.WriteLine($"抱歉,{title}不可借阅。");
        }
    }

    public void ReturnBook(string title)
    {
        Book book = books.Find(b => b.Title == title);
        if (book != null &&!book.IsAvailable)
        {
            book.IsAvailable = true;
            Console.WriteLine($"已归还书籍:{book.Title}");
        }
        else
        {
            Console.WriteLine($"无法归还,{title}可能未借阅或不存在。");
        }
    }
}

        在上述代码中,Book类表示书籍,包含书名、作者和是否可借阅的属性;Library类表示图书馆,包含添加书籍、借阅书籍和归还书籍的方法。通过这些类的协同工作,可以实现一个简单的图书馆管理功能。


十、结语

        在今后的学习和实践中,不断积累经验,深入探索 C# 的更多特性和应用场景,你将能够开发出更加复杂和高效的软件系统。希望你在编程的道路上不断前行,创造出更多优秀的作品


http://www.niftyadmin.cn/n/5864936.html

相关文章

深度学习每周学习总结Y1(Yolov5 调用官方权重进行检测 )

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客Y1中的内容 &#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制 ** 注意该训练营出现故意不退押金&#xff0c;恶意揣测偷懒用假的结果冒充真实打卡记录&#xff0c;在提出能够拿到视频录像…

《Kali Linux从安装到武器化配置:打造你的数字军火库》

0x00 颠覆式安装&#xff1a;不止于虚拟机 方案一&#xff1a;物理机裸装&#xff08;性能全开模式&#xff09; 关键步骤&#xff1a; # 禁用安全启动&#xff08;UEFI设置&#xff09; # 使用dd命令制作启动盘&#xff08;注意数据销毁警告&#xff09; sudo dd ifkal…

基于大语言模型的推荐系统(1)

推荐系统&#xff08;recommendation system&#xff09;非常重要。事实上&#xff0c;搜索引擎&#xff0c;电子商务&#xff0c;视频&#xff0c;音乐平台&#xff0c;社交网络等等&#xff0c;几乎所有互联网应用的核心就是向用户推荐内容&#xff0c;商品&#xff0c;电影&…

达梦DTS数据迁移工具生产篇(MySQL->DM8)

本文章使用的DTS工具为 2024年9月18日的版本&#xff0c;使用的目的端DM8数据库版本为2023年12月的版本&#xff0c;注意数据库版本和DTS版本之间跨度不要太大&#xff0c;以免出现各种兼容性的报错。若发现版本差距过大时&#xff0c;请联系达梦技术服务工程师处理。 1. 迁移…

Pytorch使用手册-音频 I/O(专题十八)

音频输入/输出 本教程展示了如何使用TorchAudio的基本输入/输出(I/O)API来检查音频数据,将其加载到PyTorch张量中,并保存PyTorch张量。 警告 在最近的版本中,音频输入/输出进行了多个计划或已实施的更改。有关这些更改的详细信息,请参考“Dispatcher 介绍”。 import to…

01 冲突域和广播域的划分

目录 1、冲突域和广播域的划分 1.1、冲突域 1.2、广播域 1.3、对比总结 1.4、冲突域与广播域个数计算例题 2、交换机和路由器的结构 2.1、交换机的结构 2.2、路由器的结构 1、冲突域和广播域的划分 1.1、冲突域 冲突域是指网络中可能发生数据帧冲突的物理范围。当多…

使用Socket编写超牛的http服务器和客户端(一)

实现一个高性能的基于 IOCP(I/O Completion Ports)的 HTTP 服务器,支持多线程、动态线程池调整和路由处理。 主要功能和特性 IOCP 模型: 使用多个 IOCP 句柄(IOCP_COUNT),将客户端连接均匀分配到不同的 IOCP 上,减少线程竞争。 工作线程使用 GetQueuedCompletionStatu…

短剧源码搭建部署海外短剧系统

随着海外短剧市场的蓬勃发展&#xff0c;越来越多的企业和个人希望搭建自己的短剧平台&#xff0c;以满足全球用户的需求。本文将详细介绍如何使用PHP开发、搭建、部署并上线一个海外短剧系统。整个过程将涵盖需求分析、技术选型、系统架构设计、开发流程、测试、部署以及上线后…