Menu
CoddyTech

访问修饰符

本课属于 Coddy C# 学习旅程的“面向对象编程”单元。第 31 课,共 70 课。

访问修饰符用于控制谁可以查看和使用类成员。它们是封装的基础,而封装是 OOP 的核心原则之一。通过限制访问,你可以保护数据,并在代码中划分清晰的边界。

C# 提供了 4 种主要的访问修饰符:

public class BankAccount
{
    public string AccountHolder;      // 可以从任何地方访问
    private decimal balance;          // 只能在此类内部访问
    protected string accountType;     // 可以在此类及其派生类中访问
    internal int branchCode;          // 可以在同一程序集中访问
}

public 成员可以被任何代码访问。

private 成员只能在同一个类中访问,这是限制最严格的访问级别,也是类成员的默认访问级别。

protected 允许类本身及任何继承它的类访问。

internal 将代码的访问范围限制在同一程序集(项目)内。

未指定修饰符时,类成员默认是 private:

class Example
{
    int secret;  // 默认是私有的
}

选择合适的访问级别,就是只公开必要的内容。从 private 开始,只有在有明确理由时才提高可见性。这样可以避免其他代码依赖你之后可能想要更改的实现细节。

challenge icon

挑战

简单

让我们构建一个安全的用户资料系统,展示访问修饰符如何保护敏感数据,同时只公开必要的信息。你将创建一个类,根据访问者的身份,为不同的信息设置不同的可见级别。

你需要将代码分成三个文件:

  • UserProfile.cs:在 Security 命名空间中创建一个 UserProfile 类,用合适的访问级别管理用户信息。用户资料应包含:
    • 一个 public 属性 Username(字符串),任何人都可以查看用户名
    • 一个 private 字段 password(字符串),只有类本身可以访问
    • 一个 protected 字段 email(字符串),该类及其子类可以访问
    • 一个 internal 字段 userId(整数),可在同一程序集内访问
    添加一个接受 username、password、email 和 userId 的构造函数。添加一个名为 GetPublicInfo() 的 public 方法,返回 "User: {Username}"。再添加一个名为 ValidatePassword(string input) 的 public 方法:如果输入与私有密码匹配,则返回 true,否则返回 false。
  • AdminProfile.cs:在 Security 命名空间中创建一个继承自 UserProfile 的 AdminProfile 类。这个类展示了 protected 成员如何在派生类中变得可访问。构造函数应接受相同的四个参数,并将它们传递给基类构造函数。添加一个名为 GetAdminInfo() 的 public 方法,返回 "Admin: {Username}, Email: {email}",注意,你可以在这里访问受保护的 email 字段!
  • Program.cs:在主文件中,使用输入值创建一个 UserProfile 和一个 AdminProfile。通过调用可用的公共方法并直接访问内部字段(因为你位于同一程序集内)来展示不同的访问级别。显示每种用户类型可以公开哪些信息。

你将收到五个输入值:

  • 用户名
  • 密码
  • 电子邮件
  • 用户 ID(整数)
  • 要验证的密码尝试

按以下格式输出:

Regular User:
{GetPublicInfo() result}
Internal ID: {userId}
Password valid: {ValidatePassword result}
Admin User:
{GetAdminInfo() result}

例如,如果输入是 alice、secret123、alice@email.com、1001 和 secret123,输出应为:

Regular User:
User: alice
Internal ID: 1001
Password valid: True
Admin User:
Admin: alice, Email: alice@email.com

请注意,密码始终完全隐藏,你只能验证密码,不能读取它。电子邮件受到保护,因此只有 AdminProfile(派生类)可以公开它。由于主文件位于同一程序集内,因此可以访问内部字段 userId。这就是封装的实际应用!

亲手试试

using System;
using Security;

class Program
{
    public static void Main(string[] args)
    {
        // 读取输入
        string username = Console.ReadLine();
        string password = Console.ReadLine();
        string email = Console.ReadLine();
        int userId = Convert.ToInt32(Console.ReadLine());
        string passwordAttempt = Console.ReadLine();

        // TODO:用输入值创建一个 UserProfile 对象

        // TODO:用相同的输入值创建一个 AdminProfile 对象

        // TODO:打印 "Regular User:"

        // TODO:打印 GetPublicInfo() 的结果

        // TODO:先打印 "Internal ID: ",再打印 userId 字段(因为在同一程序集内,所以可以访问)

        // TODO:先打印 "Password valid: ",再打印 ValidatePassword() 的结果

        // TODO:打印 "Admin User:"

        // TODO:打印 GetAdminInfo() 的结果
    }
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: C# 在线编译器