C# - 封装:初学者指南

你好,未来的编码超级巨星!今天,我们将踏上一段激动人心的旅程,探索C#世界的其中一个基本概念:封装。如果你之前从未编写过一行代码,也不用担心——我会一步一步地引导你。那么,让我们开始吧!

C# - Encapsulation

什么是封装?

在我们深入了解之前,先来理解一下封装究竟是什么。想象你有一个能做神奇事情的魔法盒子,但你不需要知道它内部是如何工作的——你只需要知道如何使用它。这就是封装的精髓!

在C#中,封装是将数据(变量)和操作这些数据的方法捆绑在单个单元或对象中的过程。就像是给你的代码创建了一个保护性的胶囊,因此得名“封装”。

现在,让我们探讨一下C#如何通过访问修饰符来实现封装。

C#中的访问修饰符

访问修饰符是用于定义类、方法或属性在代码中的可访问性的关键字。可以将其视为不同级别的安全许可。C#提供了五个主要的访问修饰符:

  1. 公共(Public)
  2. 私有(Private)
  3. 受保护(Protected)
  4. 内部(Internal)
  5. 受保护内部(Protected Internal)

让我们一一分解它们。

公共访问修饰符

public关键字就像是一个“通行无阻”的通行证。当你将一个成员声明为public时,它可以从程序的任何部分访问。

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

public void SayHello()
{
Console.WriteLine($"你好,我的名字是{Name}!");
}
}

class Program
{
static void Main(string[] args)
{
Person person = new Person();
person.Name = "Alice";  // 访问公共属性
person.SayHello();  // 调用公共方法
}
}

在这个例子中,NameSayHello()都是public的,因此我们可以直接从Main方法中访问它们。

私有访问修饰符

现在,private就像是一个“员工专用”的区域。私有成员只能在同一个类中访问。

public class BankAccount
{
private double balance;

public void Deposit(double amount)
{
if (amount > 0)
{
balance += amount;
}
}

public double GetBalance()
{
return balance;
}
}

class Program
{
static void Main(string[] args)
{
BankAccount account = new BankAccount();
account.Deposit(100);
// account.balance = 1000000;  // 这将导致错误!
Console.WriteLine($"余额:{account.GetBalance()}");
}
}

在这里,balance是私有的,所以我们不能从BankAccount类的外部直接访问它。我们需要使用如Deposit()GetBalance()这样的公共方法来与其交互。

受保护访问修饰符

protected成员在同一个类和派生类中可访问。它就像是一个“家庭专用”的部分。

public class Animal
{
protected string name;

public Animal(string name)
{
this.name = name;
}

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

public class Dog : Animal
{
public Dog(string name) : base(name) { }

public void Bark()
{
Console.WriteLine($"{name}正在吠叫!");  // 可以访问受保护成员
Eat();  // 可以调用受保护方法
}
}

class Program
{
static void Main(string[] args)
{
Dog dog = new Dog("Buddy");
dog.Bark();
// dog.name = "Max";  // 这将导致错误!
// dog.Eat();  // 这也将导致错误!
}
}

在这个例子中,Dog可以访问其父类Animal中的受保护的nameEat()方法,但我们不能从Main方法中直接访问这些。

内部访问修饰符

internal成员在同一程序集(可以将其视为编译后的.dll或.exe文件)内可访问。它就像是一个“公司员工专用”的区域。

// 在AssemblyOne.cs中
internal class InternalClass
{
internal void InternalMethod()
{
Console.WriteLine("这是一个内部方法。");
}
}

// 在Program.cs中(同一程序集)
class Program
{
static void Main(string[] args)
{
InternalClass obj = new InternalClass();
obj.InternalMethod();  // 这有效!
}
}

// 在不同的程序集中,这将不起作用:
// InternalClass obj = new InternalClass();  // 错误!

受保护内部访问修饰符

最后,protected internalprotectedinternal的组合。它可以在同一程序集中或由其他程序集中的派生类访问。

// 在AssemblyOne.cs中
public class BaseClass
{
protected internal void ProtectedInternalMethod()
{
Console.WriteLine("这是一个受保护内部方法。");
}
}

// 在AssemblyTwo.cs中
public class DerivedClass : BaseClass
{
public void CallProtectedInternalMethod()
{
ProtectedInternalMethod();  // 这有效!
}
}

// 在Program.cs中(AssemblyTwo)
class Program
{
static void Main(string[] args)
{
DerivedClass obj = new DerivedClass();
obj.CallProtectedInternalMethod();
// obj.ProtectedInternalMethod();  // 这将不起作用!
}
}

访问修饰符总结

这里有一个方便的表格,总结了访问级别:

访问修饰符 同一个类 派生类(同一程序集) 非派生类(同一程序集) 派生类(不同程序集) 非派生类(不同程序集)
公共
私有
受保护
内部
受保护内部

就是这样!你刚刚迈出了C#封装世界的第一步。记住,封装是关于控制对你的代码和数据的访问。它帮助你编写更安全、可维护和灵活的程序。

随着你继续编码之旅,你会发现封装变得习以为常。这就像学习骑自行车——一开始可能会有些摇晃,但很快你就能自如地骑行而无需多加思考!

继续练习,保持好奇心,快乐编码!

Credits: Image by storyset