封装与属性

封装

封装是面向对象oop的四大基本原则之一(其他三个是继承,多态,抽象)

封装的核心思想

  1. 将数据(字段)和操作数据的方法捆绑在一起,形成一个类
  2. 控制对内部实现细节的访问,将对象的内部状态(字段)隐藏起来只通过一个公开的,受控的接口(通常是属性和方法)与外部进行交互

为什么需要封装?

  1. 数据保护
  • 防止非法修改:直接暴露类的内部字段是非常危险的,外部代码可以随意不受限制的修改这个字段的值,可能导致对象处于无效或不一致的状态(如年龄为负数,账户余额被随意扣除)
  • 验证和控制:通过封装,你可以在设置值之前进行验证是否在合理范围内。如果无效值可以抛出异常,忽略请求或进行修正确保对象状态始终有效
  1. 隐藏实现细节
  • 外部代码不需要知道对象是如何存储数据或执行操作的,它只需要知道对象提供了哪些方法和设置/获取哪些信息
  1. 提高灵活性和可维护性

  2. 增强安全性

  • 敏感数据可标记为private防止外部代码直接访问和篡改

访问修饰符

访问修饰符是实现封装的关键工具,它控制类成员的可访问范围

  1. public 访问不受限。用于定义公共接口
  2. private 访问仅限于包含的它的类或结构体内部。这是类成员的默认访问级别。用于隐藏内部实现细节
  3. protected 访问仅限于包含它的类以及从该类派生的类
  4. internal 访问限于当前程序集。
  5. protected internal 访问限于当前程序集或从包含类派生的类型
  6. private protected 访问仅限于包含它的类或当前程序续集中从该类派生的类型

属性

属性是c#中实现分封装的一种强大机制,它提供了一种访问类或对象数据成员的替代方式,看起来像访问字段,实际上是通过方法(访问器)来执行

它的基本语法

csharp 复制代码
namespace ConsoleApp1
{
    class Myclass 
    {
        //类成员默认是私有字段 存储实际数据
        string _name;
        int _age;
        //我们可以通过定义一个(公共的接口)Name成员来对_name进行访问和修改,这样我们可以保证私有字段始终有效
        public string Name 
        {
            get { return _name; } //get访问器 读取值
            set { _name = value; }//set访问器 设置值  value是隐式参数 隐式参数是指那些没有在方法签名中显示声明,但可以在方法内部访问的参数

        }
        public int Age 
        { 
            get { return _age; }
            set 
            {
                //我们可以在set属性中判断值是否有效 无效抛出异常,有效直接给私有字段_age赋值
                if (value >= 0 && value <= 150)
                    _age = value;
                else
                    //无效抛出异常的代码逻辑
                    Console.WriteLine("抛出异常代码");
            } 
        }
    }
    internal class Program
    {
        static void Main(string[] args)
        {
           Myclass class1 = new Myclass();
            class1.Name = "张三";
            class1.Age = 100;
            Console.WriteLine($"姓名{class1.Name}今年{class1.Age}");
        }
    }
}

关键组成部分

  1. get访问器:
  • 当读取属性值时调用
  • 必须返回一个与属性值类型匹配的的值
  • 可以包含逻辑(如计算,返回默认值等)
  • 语法:get{...return...;}
  1. set访问器:
  • 当为属性赋值时调用
  • 有一个隐式参数value 其类型与属性类型相同 代表要赋值的值
  • 通常用于将值存储到私有字段中
  • 可以包含验证逻辑,通知逻辑,日志记录等
  • 语法set{...}
  1. 访问器可见性
  • 默认情况下 get和set访问器具有与属性本身相同的访问级别
  • 也可以单独修改访问器的可见性(通常用于创建只读或只写属性)
csharp 复制代码
public string ReadOnlyName { get; private set; } // 外部只读,类内部可写
public int WriteOnlyId { private get; set; }    // 外部只写,类内部可读 (较少见)

属性的优势

  • 访问控制:提供对字段读写操作的完全控制
  • 添加逻辑:可以在get/set中添加验证计算等逻辑代码
  • 数据绑定友好:属性是数据绑定机制的标准方式
  • 语法简洁
自动属性

对于不需要在get/set中添加额外逻辑的简单属性,我们可以用自动属性

csharp 复制代码
public class Person
{
    // 自动属性 - 编译器会自动生成一个隐藏的私有后备字段
    public string Name { get; set; }
    public int Age { get; set; }
}
  • 工作原理:编译器会在编译时自动为你生成一个私有的匿名的后备字段,并实现基于get和set访问器来操作这个字段
  • 初始胡:可以在声明时初始化public int a {get;set;}=1;
  • 只读自动属性 在构造函数中初始化
csharp 复制代码
public class Person
{
    public string Id {get;}//只读自动属性(没有set 如果想要初始化需要在构造函数中初始化)
    public Person(int id)
    {
        Id = id;
    }
}
  • 使用init访问器允许在对象初始化器中赋值
csharp 复制代码
namespace ConsoleApp1
{
    class Myclass 
    {
        //可以在构造函数或对象初始化器中赋值
        public int b { get; init; }
        }
    }
    internal class Program
    {
        static void Main(string[] args)
        {
           Myclass class1 = new Myclass { b=1 };//对象初始化器
            
        }
    }
}

总结

  • 封装是oop的核心原则,旨在保护数据,隐藏代码细节提高代码安全性和可维护性
  • 访问修饰符是实现封装的基础控制成员的可见性
  • 属性是c#中实现数据封装的首选方式。通过get和set访问器提供对私有字段的受控访问,允许添加验证和逻辑
  • 自动属性简化了不需要的额外逻辑属性的声明,编译器自动处理后备字段和基本访问器
  • 优先使用属性而不是公共字段来暴露类的数据成员
相关推荐
LostXerxes2 小时前
C#类与对象
c#
最美的不是下雨天4 小时前
为什么要用async、await ?
c#
NullReference5 小时前
记一次WPF程序界面卡死的情况
c#
秋月的私语5 小时前
wpf程序启动居中并且最小化到托盘修复记录
c#
木心爱编程9 小时前
C++程序员速通C#:从Hello World到数据类型
c++·c#
※※冰馨※※9 小时前
【c#】 使用winform如何将一个船的图标(ship.png)添加到资源文件
开发语言·windows·c#
咕白m62510 小时前
C# 实现 Word 与 TXT 文本格式互转
c#·.net
土了个豆子的1 天前
04.事件中心模块
开发语言·前端·visualstudio·单例模式·c#