首页 > 编程笔记 > C#笔记 阅读:24

C#封装用法详解(附带实例)

C# 程序中,我们可以从顶级语句直接引用所设计的类内的成员变量(属性)和方法,像这种类内的成员变量可以让外部引用的称为公有属性,而可以让外部引用的方法称为公有方法。

所有类的属性与方法可供外部随意存取,这个设计概念最大的风险就是会有信息安全的疑虑。

【实例 1】下面是一个简单的 Bank 类,这个类创建对象完成后,会将存款金额(balance)设为 0,但是我们可以在顶级语句中随意设定 balance,即可以获得目前的存款余额。
Bank A = new Bank("Hung");
A.GetBalance();
A.balance = 1000;
A.GetBalance();

public class Bank
{
    public int balance;
    public string name;
    public Bank(string name)
    {
        this.name = name;
        this.balance = 0;
    }
    public void GetBalance()
    {
        Console.WriteLine($"{name} 目前存款余额 {this.balance}");
    }
}
执行结果为:

Hung 目前存款余额 0
Hung 目前存款余额 1000

上述程序设计最大的风险是 Bank 类外的顶级语句可以随意改变存款余额,如此造成信息上的不安全。其概念可以参考下图:


为了确保类内成员变量(属性值)的安全,有必要限制外部使其无法直接存取类内的成员变量(属性值)。这其实就是将类的成员变量隐藏起来,未来如果想要存取被隐藏的成员变量,就需使用此类的方法,外部无法得知类内是如何运作的,这个概念就是所谓的封装(encapsulation),有时候又称信息隐藏(information hiding)。此时程序设计的概念应如下所示:

C#类成员的访问控制

到目前为止,笔者所设计的类内的方法大都没有加上 public 存取修饰符(access modifier),其实可以将访问控制分成 6 个等级。

位置 public protected internal protected internal private protected private
类内 Y Y Y Y Y Y
衍生类
(相同项目)
Y Y Y Y Y N
非衍生类
(相同项目)
Y Y N Y N N
衍生类
(不同项目)
Y Y Y N N N
非衍生类
(不同项目)
Y N N N N N

上述列表指出了类成员有关存取修饰符的权限,下列将分别说明:

C#设计具有封装效果的程序

这里继续用 Bank 的实例说明,程序设计时若是想要类内的成员变量(属性)是安全的,无法由外部随意存取,则必须将成员变量设计为 private,其实成员变量默认就是 private。

为了可以存取这些 private 的成员变量,我们必须在 Bank 类内设计可以供顶级语句设定并取得存款金额的程序。

【实例 2】将 Bank 类数据 balance 设为 private,然后顶级语句无法存取,需使用 public 类的 void SetBalance()方法和int GetBalance() 方法,来设定并取得存款余额。
Bank A = new Bank();
A.SetBalance(1000);
Console.WriteLine(A.GetBalance());
public class Bank
{
    private int balance; // 默认的也是 private,所以也可以省略 private
    public void SetBalance(int balance)
    {
        this.balance = balance; // 设定存款余额
    }
    public int GetBalance()
    {
        return balance; // 回传存款金额
    }
}
执行结果为:

1000

上述程序中,为了区分传递参数的 balance 与类定义的 balance,笔者使用了 this 关键词,读者可以参考第 11 行,C# 程序设计时喜欢使用“下画线+变量名称”来定义类内的成员字段变量,读者可以参考下列实例。

【实例 3】使用下面线定义成员变量。
Bank A = new Bank();
A.SetBalance(1000);
Console.WriteLine(A.GetBalance());

public class Bank
{
    private int _balance; // 默认的也是 private,所以也可以省略 private
    public void SetBalance(int balance)
    {
        _balance = balance; // 设定存款余额
    }
    public int GetBalance()
    {
        return _balance; // 回传存款金额
    }
}
执行结果与实例 2 相同。

相关文章