C# 封装
封装(Encapsulation)是面向对象编程(OOP)的四大基本原则之一。它指的是将数据(属性)和行为(方法)捆绑在一起,并对外隐藏内部实现的细节。通过封装,我们可以控制对类成员的访问,从而保护数据不被外部直接修改或滥用。
为什么需要封装?
封装的主要目的是:
- 保护数据:防止外部代码直接访问或修改类的内部数据,确保数据的完整性和安全性。
- 隐藏实现细节:只暴露必要的接口,隐藏复杂的内部逻辑,使代码更易于维护和扩展。
- 提高代码复用性:通过封装,可以将功能模块化,便于在其他地方复用。
访问修饰符
在C#中,封装通过访问修饰符来实现。常用的访问修饰符包括:
public
:成员可以从任何地方访问。private
:成员只能在定义它的类内部访问。protected
:成员可以在定义它的类及其派生类中访问。internal
:成员可以在同一程序集(Assembly)中访问。
示例:使用 private
和 public
csharp
public class BankAccount
{
private double balance; // 私有字段,外部无法直接访问
public BankAccount(double initialBalance)
{
balance = initialBalance;
}
public void Deposit(double amount)
{
if (amount > 0)
{
balance += amount;
}
}
public void Withdraw(double amount)
{
if (amount > 0 && amount <= balance)
{
balance -= amount;
}
}
public double GetBalance()
{
return balance;
}
}
在上面的代码中,balance
字段被声明为 private
,因此外部代码无法直接修改它。我们通过 Deposit
和 Withdraw
方法来控制对 balance
的修改,并通过 GetBalance
方法提供只读访问。
属性的封装
C# 提供了属性(Property)来实现更优雅的封装。属性允许我们定义 get
和 set
访问器,从而控制对字段的访问。
示例:使用属性封装字段
csharp
public class BankAccount
{
private double balance;
public double Balance
{
get { return balance; }
private set { balance = value; } // 只能在类内部修改
}
public BankAccount(double initialBalance)
{
Balance = initialBalance;
}
public void Deposit(double amount)
{
if (amount > 0)
{
Balance += amount;
}
}
public void Withdraw(double amount)
{
if (amount > 0 && amount <= Balance)
{
Balance -= amount;
}
}
}
在这个例子中,Balance
属性提供了对 balance
字段的访问。set
访问器被声明为 private
,因此只能在类内部修改 balance
。
实际案例:用户管理系统
假设我们正在开发一个用户管理系统,需要封装用户的敏感信息(如密码)。
csharp
public class User
{
private string username;
private string password;
public string Username
{
get { return username; }
set { username = value; }
}
public string Password
{
private get { return password; }
set { password = HashPassword(value); } // 密码存储为哈希值
}
private string HashPassword(string input)
{
// 模拟密码哈希处理
return $"HASHED_{input}";
}
public bool VerifyPassword(string input)
{
return HashPassword(input) == password;
}
}
在这个案例中,Password
属性被封装,外部代码无法直接获取原始密码,只能通过 VerifyPassword
方法验证密码是否正确。
总结
封装是面向对象编程的核心概念之一,它通过访问修饰符和属性来保护数据并隐藏实现细节。通过封装,我们可以编写更安全、更易于维护的代码。
附加资源
练习
- 创建一个
Person
类,封装Name
和Age
属性,确保Age
不能为负数。 - 设计一个
Car
类,封装Speed
属性,并提供一个方法Accelerate
来增加速度,但不能超过最大速度限制。