C# 初级教程(三) 封装与访问修饰符
参考文章
C# 中的类、结构和记录 | Microsoft Learn
访问修饰符 - C# 参考 | Microsoft Learn
1 前提回顾-抽象
C# 初级教程(二) 面向对象的编程1_theifWhoStealsMoon的博客-CSDN博客
上一节讲到了面向对象的四个原则(微软官方认为是三个原则),其中的第一个原则 抽象,描绘的是如何将现实中的问题和事物转化为面向对象程序中的 类Class,通过一定的方法,我们将Dog 做成了一个模板,成功的描绘了现实世界中一类狗狗的特征属性。
而这里提到的 将Dog 做成模板的一定的方法就是今天要讲的内容 封装。
2 面向对象-封装
在微软官方文档中,封装被称为面向对象的i第一支柱或者原则。可见封装这个概念在面向对象编程中多么重要。
封装非常好理解,我们将某些东西做成了一个数据+方法的集合,这个过程可以叫做分类,类似于在整理文件时,将不同类型的文件放在同一个文件夹内。封装在分类的基础上,又增加了一项功能,就是访问权限的设置。
看以下示例:
public class Phones
{
public double screenSize;//屏幕尺寸
public double Weight;//重量
public Colors color;//颜色
private string data;//手机的内部资料
private string passWord;//手机的密码
protected double costPrice = "2000";//手机的成本价格
protected string keyTechnology;//手机的核心技术
}
这个例子给出的是一个phone的抽象模板,包含6个字段/属性。这7个字段属性是所有手机都共有的,是一个合格的模板。
但是我们注意到这7个字段/属性最前的修饰符却不相同,有3种修饰符,分别是 public、private、protected,这3种修饰符就代表了所分类出的集合中的元素的访问权限,同时体现了封装的思想。
对于某一个特定的phone 对象来说,作为顾客,我们希望能够知道手机的屏幕尺寸、重量、颜色等在内的一些参数;作为手机的使用者,我们希望访问手机的内部资料和密码;作为手机的开发者,我们希望知道手机的成本以及核心技术。很明显这三种类中的字段具有不同的 访问权限 。因此就引出 访问修饰符 。
2.1 访问修饰符
访问修饰符在用于所要定义的变量之前,表示该变量的访问权限。常用的主要有以下几个访问修饰符:
public //公有的
private //私有的
protected //受保护的
internal //内部的
2.1.1 public
public 公共访问,是最高的访问级别,对修饰的成员没有访问限制,认为是完全公开的访问权限。以下示例可以看到:
//使用上文的 Phones 类
class Program
{
static void Main()
{
Phones phone = new Phones();
phone.screenSize = 14;
phone.weight = 200;
Console.WriteLine($"screenSize = {phone.screenSize},weight = {phone.weight}");
}
}
screenSize和weight都作为phone的共有变量,可以被访问到,所以输出结果为:
screenSize = 14,weight = 200
2.1.2 private
private 私有访问,是最低的访问级别。被其修饰的成员只有在声明它们的类或者结构体中,才是可以访问的。可以看以下示例:
//使用上文的 Phones 类 并加以修改
public class Phones
{
public double screenSize;//屏幕尺寸
public double Weight;//重量
public Colors color;//颜色
private string data = "11";//手机的内部资料
private string passWord = "123";//手机的密码
protected double costPrice;//手机的成本价格
protected string keyTechnology;//手机的核心技术
public string GetData()
{
return data;
}
public string GetPassword
{
get {return passWord;}
}
}
class Program
{
static void Main()
{
Phones phone = new Phones();
phone.data = "数据"; //报错
phone.passWord = "12345"; //报错
Console.WriteLine("data为 " + phone.GetData());
Console.WriteLine("passWord为 " + phone.GetPassword);
}
}
以上的示例中,data,passWord都是Phones 类中的私有变量,因此当尝试在其它类中去访问并且修改它时会报错。

但是下面两行却能够正常输出,

这是因为data使用了公有方法GetData()在Phones类里面去访问;而passWord则是由公有字段GetPassword去访问,从而实现了在声明的类中去访问。因此可以获得其值。
2.1.3 protected
protected 受保护的访问,被其修饰的变量或者方法仅限于包含类或者派生自包含类的类型。派生是面向对象中的另一个关键词,可以期待我接下来的文章,也可以参阅 继承与派生 | Microsoft Learn。
protected 的访问权限要高于 private,可以看以下示例:
//使用上文的 Phones 类
public class HuaWeiPhones : Phones //HuaWeiPhones继承Phones类
{
public double GetCostPrice()
{
return costPrice;
}
}
static void Main()
{
Phones phone = new Phones();
HuaWeiPhones huaWeiPhone = new HuaWeiPhones();//实例化HuaWeiPhones
Console.WriteLine("costPrice为 " + huaWeiPhone.GetCostPrice());
}
在此示例中,HuaWeiPhones 继承 Phones ,HuaWeiPhones 是 由 Phones 派生 的类,因此HuaWeiPhones 具有所有Phones 拥有的属性,而且它可以访问到Phones 中被 protected 修饰的costPrice字段。以上示例输出为:

2.1.4 internal
internal 内部的访问,其修饰的变量访问仅限于当前的程序集,即只有在当前的文件中才能访问到internal所修饰的变量。
此示例包含两个文件/程序集,即 Assembly1.cs 和 Assembly1_a.cs。 第一个文件包含内部基类 BaseClass。 在第二个文件中,尝试实例化 BaseClass 会产生错误。
// Assembly1.cs
// Compile with: /target:library
internal class BaseClass
{
public static int intM = 0;
}
// Assembly1_a.cs
// Compile with: /reference:Assembly1.dll
class TestAccess
{
static void Main()
{
var myBase = new BaseClass(); // CS0122
}
}
因为BaseClass 被 internal修饰,所以BaseClass在其他的文件中不能被访问,因此会发生报错。
3 结语
通过对事物进行抽象,可以将事物有关的属性和方法封装进一个集合成为类;在封装的过程中,通过访问修饰符使得不同的属性和方法具有不同的访问权限,实现了数据选择性展示的功能。
封装使得类中的数据变得安全可靠,也为面向对象的变成奠定了安全基础。