封装是面向对象编程(OOP)中的核心概念之一,它的作用是隐藏对象的内部实现细节,只暴露必要的接口,以便外部代码能够与之交互。在 C# 中,封装通过访问修饰符来实现。访问修饰符决定了类成员(如字段、属性和方法)能被哪些代码访问。这篇文章将深入探讨 C# 中的封装,解释不同的访问修饰符,并通过示例帮助理解。
一、封装的定义
封装可以被定义为"将一个或多个项目封闭在一个物理或逻辑的包中"。在面向对象编程中,封装的主要目的是隐藏实现细节,暴露接口。通过封装,程序员可以控制类内部数据的访问权限,并根据需要决定哪些信息可以被外部代码访问。
封装与抽象密切相关,抽象允许开发者设计类的高层次接口,封装则实现了对类的具体实现细节的控制。简而言之,封装是实现抽象的一种手段。
二、访问修饰符
C# 提供了多种访问修饰符来控制类成员的可见性和访问范围。下面列出的是 C# 中常用的访问修饰符:
- public:该成员对所有代码都可见,其他类和程序集可以访问。
- private:该成员只能在本类中访问,外部类无法访问。
- protected:该成员只能在本类及其派生类中访问。
- internal:该成员只能在当前程序集中访问,其他程序集无法访问。
- protected internal:该成员可以在当前程序集内访问,也可以在派生类中访问。
接下来,我们将通过一些代码示例来深入理解这些访问修饰符。
1. Public 访问修饰符
public 访问修饰符意味着类的成员对所有外部代码都是可见的。在使用 public 修饰符时,可以直接访问类的字段或方法。
示例:
csharp
using System;
namespace RectangleApplication
{
class Rectangle
{
// 公共成员变量
public double length;
public double width;
public double GetArea()
{
return length * width;
}
public void Display()
{
Console.WriteLine("长度: {0}", length);
Console.WriteLine("宽度: {0}", width);
Console.WriteLine("面积: {0}", GetArea());
}
}
class ExecuteRectangle
{
static void Main(string[] args)
{
Rectangle r = new Rectangle();
r.length = 4.5;
r.width = 3.5;
r.Display();
Console.ReadLine();
}
}
}
输出:
长度: 4.5
宽度: 3.5
面积: 15.75
在上面的代码中,length 和 width 都被声明为 public,因此它们可以被外部类 ExecuteRectangle 直接访问。这就是封装的一个简单例子,使用 public 访问修饰符暴露了类的部分成员。
2. Private 访问修饰符
private 访问修饰符意味着类的成员只能在本类内部访问,外部无法直接访问。这有助于保护对象的状态,只允许通过类提供的公共方法来修改或获取数据。
示例:
csharp
using System;
namespace RectangleApplication
{
class Rectangle
{
// 私有成员变量
private double length;
private double width;
// 公共方法,用于设置矩形的长度和宽度
public void AcceptDetails()
{
Console.WriteLine("请输入长度:");
length = Convert.ToDouble(Console.ReadLine());
Console.WriteLine("请输入宽度:");
width = Convert.ToDouble(Console.ReadLine());
}
// 公共方法,用于计算矩形的面积
public double GetArea()
{
return length * width;
}
// 公共方法,用于显示矩形的属性和面积
public void Display()
{
Console.WriteLine("长度: {0}", length);
Console.WriteLine("宽度: {0}", width);
Console.WriteLine("面积: {0}", GetArea());
}
}
class ExecuteRectangle
{
static void Main(string[] args)
{
// 创建 Rectangle 类的实例
Rectangle r = new Rectangle();
// 通过公有方法 AcceptDetails() 获取矩形的长度和宽度
r.AcceptDetails();
// 通过公有方法 Display() 显示矩形的属性和面积
r.Display();
Console.ReadLine();
}
}
}
输出:
请输入长度:
5
请输入宽度:
3
长度: 5
宽度: 3
面积: 15
在这个示例中,length 和 width 被声明为 private,因此它们无法直接在外部访问。我们通过公共方法 AcceptDetails() 来获取用户输入,并通过 Display() 方法来显示矩形的属性。这样就实现了对类内部数据的保护。
3. Protected 访问修饰符
protected 访问修饰符意味着成员只能在当前类及其派生类中访问。它通常用于继承中,让子类可以访问基类的成员。
示例:
csharp
using System;
namespace RectangleApplication
{
class Rectangle
{
// 保护成员变量
protected double length;
protected double width;
public void SetDimensions(double l, double w)
{
length = l;
width = w;
}
}
class Square : Rectangle
{
public void Display()
{
Console.WriteLine("边长: {0}", length); // 继承自 Rectangle 类
}
}
class ExecuteRectangle
{
static void Main(string[] args)
{
Square s = new Square();
s.SetDimensions(5.0, 5.0);
s.Display();
Console.ReadLine();
}
}
}
输出:
边长: 5
在上面的代码中,length 和 width 使用 protected 访问修饰符,因此可以在 Square 类中访问。这是通过继承实现的,Square 作为 Rectangle 的派生类,可以访问基类的受保护成员。
4. Internal 访问修饰符
internal 访问修饰符允许在同一程序集中的其他类访问该成员,但不允许外部程序集访问。它是限制访问范围的一种方式。
示例:
csharp
using System;
namespace RectangleApplication
{
class Rectangle
{
// 内部成员变量
internal double length;
internal double width;
public double GetArea()
{
return length * width;
}
public void Display()
{
Console.WriteLine("长度: {0}", length);
Console.WriteLine("宽度: {0}", width);
Console.WriteLine("面积: {0}", GetArea());
}
}
class ExecuteRectangle
{
static void Main(string[] args)
{
Rectangle r = new Rectangle();
r.length = 4.5;
r.width = 3.5;
r.Display();
Console.ReadLine();
}
}
}
输出:
长度: 4.5
宽度: 3.5
面积: 15.75
在这个示例中,length 和 width 使用 internal 修饰符,因此它们可以在同一程序集内的任何类中访问。
5. Protected Internal 访问修饰符
protected internal 访问修饰符意味着成员可以在当前程序集中访问,也可以在派生类中访问。
示例:
csharp
using System;
namespace RectangleApplication
{
class Rectangle
{
// 保护内部成员变量
protected internal double length;
protected internal double width;
public double GetArea()
{
return length * width;
}
public void Display()
{
Console.WriteLine("长度: {0}", length);
Console.WriteLine("宽度: {0}", width);
Console.WriteLine("面积: {0}", GetArea());
}
}
class ExecuteRectangle
{
static void Main(string[] args)
{
Rectangle r = new Rectangle();
r.length = 4.5;
r.width = 3.5;
r.Display();
Console.ReadLine();
}
}
}
输出:
长度: 4.5
宽度: 3.5
面积: 15.75
在这里,length 和 width 被声明为 protected internal,因此可以在当前程序集内的任何类中访问,也可以在派生类中访问。
三、总结
通过合理使用访问修饰符,C# 提供了一种强大的方式来实现封装,保护对象的内部状态,并提供清晰的接口与外部交互。封装