-
类与对象——用C#开发图书管理系统基础模型
第一部分:C#基础入门
实例1:类与对象——图书管理系统基础模型
实例介绍
类与对象是面向对象编程(OOP)的核心,类是抽象的模板(如“图书”的通用定义),对象是类的具体实例(如《C#编程指南》这本具体的书)。本实例通过实现图书管理系统的基础模型,让你掌握类的定义、对象的创建、封装的意义、属性与方法的使用,理解“如何用代码描述现实世界的实体与交互”。
需求分析
1.定义核心实体类:
1.图书类(Book):包含ISBN、书名、作者、库存等属性;
2.读者类(Reader):包含读者ID、姓名、当前借阅数量等属性;
3.借阅记录类(BorrowRecord):包含图书ISBN、读者ID、借阅日期、归还日期等属性;
2.实现核心逻辑:
1.图书借阅:检查图书库存→检查读者借阅限额→更新库存与借阅数量→生成借阅记录;
2.封装属性:通过私有字段+公共属性确保数据安全(如库存不能为负、借阅数量不能超过限额);
3.模拟交互流程:创建图书/读者对象→模拟借阅操作→输出结果验证vb.net教程C#教程python教程SQL教程access 2010教程
逻辑正确性。
代码实现
csharp
using System;
using System.Collections.Generic;
namespace BookManagementSystem
{
// 1. 图书类:封装图书信息与借阅逻辑
public class Book
{
// 私有字段:封装内部数据,禁止直接修改
private string _isbn;
private string _title;
private string _author;
private int _stock;
// 构造函数:初始化对象时设置必填属性
public Book(string isbn, string title, string author, int stock)
{
_isbn = isbn;
_title = title;
_author = author;
Stock = stock; // 用属性设置库存,触发合法性检查
}
// 公共属性:控制外部访问权限,实现数据封装
public string ISBN
{
get => _isbn; // 只读:ISBN一旦创建不可修改
private set => _isbn = value;
}
public string Title { get => _title; set => _title = value; }
public string Author { get => _author; set => _author = value; }
public int Stock
{
get => _stock;
set
{
if (value < 0) throw new ArgumentException("库存不能为负数!");
_stock = value;
}
}
// 方法:判断图书是否可借阅
public bool CanBorrow() => _stock > 0;
}
// 2. 读者类:封装读者信息与借阅限额
public class Reader
{
private int _readerId;
private string _name;
private int _borrowCount;
private const int MaxBorrowCount = 3; // 最大借阅数量(常量)
public Reader(int readerId, string name)
{
_readerId = readerId;
_name = name;
_borrowCount = 0;
}
public int ReaderId { get => _readerId; private set => _readerId = value; }
public string Name { get => _name; set => _name = value; }
public int BorrowCount
{
get => _borrowCount;
private set
{
if (value > MaxBorrowCount) throw new InvalidOperationException($"最多可借阅{MaxBorrowCount}本!");
_borrowCount = value;
}
}
// 方法:判断读者是否可借阅新图书
public bool CanBorrowNewBook() => _borrowCount < MaxBorrowCount;
// 方法:增加借阅数量
public void IncreaseBorrowCount() => BorrowCount++;
}
// 3. 借阅记录类:封装借阅信息
public class BorrowRecord
{
public string BookIsbn { get; set; }
public int ReaderId { get; set; }
public DateTime BorrowDate { get; set; }
public DateTime? ReturnDate { get; set; } // 可空:未归还时为null
public BorrowRecord(string bookIsbn, int readerId)
{
BookIsbn = bookIsbn;
ReaderId = readerId;
BorrowDate = DateTime.Now;
ReturnDate = null;
}
}
// 4. 主程序:模拟借阅流程
class Program
{
static void Main(string[] args)
{
// 创建图书对象(实例化Book类)
Book csharpBook = new Book("978-7-111-55842-2", "C#编程指南", "张三", 5);
// 创建读者对象(实例化Reader类)
Reader userLi = new Reader(1001, "李四");
// 存储借阅记录的列表
List<BorrowRecord> borrowRecords = new List<BorrowRecord>();
Console.WriteLine("=== 初始状态 ===");
Console.WriteLine($"图书:{csharpBook.Title},库存:{csharpBook.Stock}");
Console.WriteLine($"读者:{userLi.Name},当前借阅数:{userLi.BorrowCount}");
// 模拟借阅操作
try
{
if (csharpBook.CanBorrow() && userLi.CanBorrowNewBook())
{
// 更新图书库存
csharpBook.Stock--;
// 更新读者借阅数
userLi.IncreaseBorrowCount();
// 生成借阅记录
borrowRecords.Add(new BorrowRecord(csharpBook.ISBN, userLi.ReaderId));
Console.WriteLine("
=== 借阅成功 ===");
Console.WriteLine($"图书库存变为:{csharpBook.Stock}");
Console.WriteLine($"读者借阅数变为:{userLi.BorrowCount}");
Console.WriteLine($"借阅记录:ISBN={csharpBook.ISBN},读者ID={userLi.ReaderId},借阅日期={DateTime.Now:yyyy-MM-dd}");
}
else
{
Console.WriteLine("
=== 借阅失败 ===");
Console.WriteLine($"原因:{(csharpBook.CanBorrow() ? "" : "图书库存不足!")}{(userLi.CanBorrowNewBook() ? "" : "读者已达借阅限额!")}");
}
}
catch (Exception ex)
{
Console.WriteLine($"
操作失败:{ex.Message}");
}
}
}
}
逐行讲解
-
Book类的封装设计
csharp
private string _isbn; // 私有字段:外部无法直接访问
public string ISBN { get => _isbn; private set => _isbn = value; }
封装的意义:用private字段隐藏内部数据,避免外部随意修改(如直接把ISBN改成空字符串);
只读属性:ISBN的set是private,意味着只能在类内部(如构造函数)赋值,确保图书ISBN的唯一性与不可变性;
库存合法性检查:Stock属性的set方法判断value是否为负,若非法则抛出异常,保证数据正确性。
2. Reader类的限额控制
csharp
private const int MaxBorrowCount =3; // 常量:固定最大借阅数
public bool CanBorrowNewBook() => _borrowCount < MaxBorrowCount;
常量定义:const修饰的字段是编译时常量,不可修改,适合存储固定规则(如借阅限额);
方法封装逻辑:CanBorrowNewBook方法隐藏“判断借阅限额”的细节,外部只需调用方法即可,无需关心内部实现;
借阅数限制:BorrowCount的set方法禁止超过MaxBorrowCount,防止读者借阅过多图书。
3. 构造函数的作用
csharp
public Book(string isbn, string title, string author, int stock)
{
_isbn = isbn;
Stock = stock; // 用属性赋值,触发库存检查
}
初始化对象:构造函数是创建对象时的“初始化函数”,确保对象创建时就有合法的状态(如必须传入ISBN、书名等必填信息);
区别于默认构造函数:若未定义构造函数,C#会自动生成无参默认构造函数;但定义带参构造函数后,默认构造函数会消失(如需保留需手动定义)。
4. 借阅逻辑的实现
csharp
if (csharpBook.CanBorrow() && userLi.CanBorrowNewBook())
{
csharpBook.Stock--;
userLi.IncreaseBorrowCount();
borrowRecords.Add(new BorrowRecord(...));
}
对象交互:图书对象与读者对象通过方法(CanBorrow/CanBorrowNewBook)协作,完成借阅操作;
引用类型特性:Book和Reader是类(引用类型),修改对象的属性时,直接作用于原对象(而非拷贝),确保数据一致性。
基础知识拓展
-
类与对象的核心概念
概念 解释 示例
类 抽象的模板,定义实体的属性与行为 Book类定义了图书的ISBN、书名、库存等属性,以及借阅相关方法
对象 类的具体实例,具有唯一的状态 csharpBook是Book类的对象,代表《C#编程指南》这本具体的书
封装 隐藏内部数据,仅暴露安全的访问接口 用private字段+public属性控制数据访问,防止非法修改
属性 字段的“包装器”,提供get/set方法 Stock属性封装_stock字段,实现库存合法性检查
方法 类的行为,封装业务逻辑 CanBorrow方法判断图书是否可借阅 -
字段 vs 属性的区别
特性 字段(Field) 属性(Property)
访问修饰符 可public/private 通常public(暴露给外部)
逻辑处理 无(仅存储数据) 可在get/set中添加逻辑(如合法性检查)
序列化支持 部分序列化工具不支持private字段 支持序列化,适合传输数据
设计原则 尽量用private隐藏 用public暴露,作为外部访问的接口 -
构造函数的重载
若需要多种初始化方式,可重载构造函数:
csharp
// 带参构造函数1:全参数
public Book(string isbn, string title, string author, int stock) { ... }
// 带参构造函数2:省略作者(默认作者为"未知")
public Book(string isbn, string title, int stock) : this(isbn, title, "未知", stock) { }
// 默认构造函数:所有属性设为默认值
public Book() : this("000000", "未知书名", "未知作者", 0) { }
this关键字:调用同一类中的其他构造函数,避免代码重复;
重载规则:参数数量或类型不同即可重载。
扩展思考
1.归还逻辑实现:如何添加ReturnBook方法,更新图书库存与读者借阅数?
2.ISBN唯一性校验:在创建Book对象时,如何检查ISBN是否已存在于系统中?
3.持久化数据:如何将图书、读者、借阅记录保存到文件(如JSON),下次启动时加载?
4.多图书借阅:如何让读者同时借阅多本图书,并生成多条借阅记录?
5.异常处理优化:如何针对不同错误场景(如库存不足、借阅限额)抛出特定异常?
总结
类与对象是面向对象编程的基石,封装是类的核心特性之一。通过图书管理系统的基础模型,你学会了:
用类定义现实世界的实体(图书、读者);
用对象创建实体的具体实例;
用私有字段+公共属性实现数据封装,确保数据安全;
用方法封装业务逻辑,简化外部调用。
掌握这些基础,你就能用代码描述更复杂的业务场景,为后续学习继承、多态等高级特性打下坚实基础。
本站原创,转载请注明出处:https://www.xin3721.com/ArticlecSharp/c49402.html










