跳到主要内容

C# 封装

封装(Encapsulation)是面向对象编程(OOP)的四大基本原则之一。它指的是将数据(属性)和行为(方法)捆绑在一起,并对外隐藏内部实现的细节。通过封装,我们可以控制对类成员的访问,从而保护数据不被外部直接修改或滥用。

为什么需要封装?

封装的主要目的是:

  1. 保护数据:防止外部代码直接访问或修改类的内部数据,确保数据的完整性和安全性。
  2. 隐藏实现细节:只暴露必要的接口,隐藏复杂的内部逻辑,使代码更易于维护和扩展。
  3. 提高代码复用性:通过封装,可以将功能模块化,便于在其他地方复用。

访问修饰符

在C#中,封装通过访问修饰符来实现。常用的访问修饰符包括:

  • public:成员可以从任何地方访问。
  • private:成员只能在定义它的类内部访问。
  • protected:成员可以在定义它的类及其派生类中访问。
  • internal:成员可以在同一程序集(Assembly)中访问。

示例:使用 privatepublic

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,因此外部代码无法直接修改它。我们通过 DepositWithdraw 方法来控制对 balance 的修改,并通过 GetBalance 方法提供只读访问。

属性的封装

C# 提供了属性(Property)来实现更优雅的封装。属性允许我们定义 getset 访问器,从而控制对字段的访问。

示例:使用属性封装字段

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 方法验证密码是否正确。

总结

封装是面向对象编程的核心概念之一,它通过访问修饰符和属性来保护数据并隐藏实现细节。通过封装,我们可以编写更安全、更易于维护的代码。

附加资源

练习

  1. 创建一个 Person 类,封装 NameAge 属性,确保 Age 不能为负数。
  2. 设计一个 Car 类,封装 Speed 属性,并提供一个方法 Accelerate 来增加速度,但不能超过最大速度限制。