⭐以下内容可能有误,请仔细甄别
1.protected访问修饰符
我们之前学了两种访问权限:
• public:完全公开,任何地方都能读写
• private:完全私有,只有当前类内部能用
在继承场景里会出现一个中间需求:父类的成员,只想让子类能直接访问,不想对外界公开。private太严(子类也碰不到),public太松(外部随便改),C#专门为这个场景设计了protected。
权限范围:当前类内部 + 所有派生类内部可访问,类外部代码无法访问
核心作用:在继承体系内权限,权限,对外依然保持封装性
举例如下
另外补充一个高频用法:属性的访问器也可以单独加protected,比如
public string Name { get;protected set;}
效果是:外界可以读取名字,但只有类内部和子类可以修改名字,比private set多了子类修改的权限。
下面介绍三个典型常用的场景
1.基类核心状态字段:子类内部需直接操作,对外严格封装
最常见于游戏开发、业务模型的基类设计。
• 场景:比如角色基类 Character 里的 _hp、_attack 等核心数值,战士、法师等子类的专属技能方法里需要频繁读写这些值,但绝对不允许外部代码直接修改。
• 为什么不用 private:子类碰不到,只能通过公开属性间接操作,子类内部写逻辑会很繁琐;
• 为什么不用 public:外部随便改数值,直接破坏封装和业务规则。
2.基类内部通用方法:仅供给子类复用,对外隐藏实现
• 场景:基类封装了通用的计算逻辑(比如伤害公式、属性校验方法),所有子类都要调用,但这个内部方法不该暴露给外部使用者。
• 作用:通用逻辑只写一遍,子类直接复用,同时对外隐藏内部实现细节。
你可以把父类想象成「后厨总厨房」,子类是「各个特色档口(川菜、粤菜)」,外部代码是「吃饭的客人」。
• 厨房里有个通用技能:切菜备料(),这个活儿每个档口都要做,但绝对不能让客人自己上手。
• 如果设成 private:只有总厨房自己能用,各个档口(子类)用不了,每个档口都得重新学一遍切菜,重复劳动;
• 如果设成 public:客人也能直接进后厨切菜,完全乱套,破坏封装;
• 设成 protected 刚好:所有后厨内部的档口(子类)都能用,客人(外部代码)碰不到。
对应到代码里:
3.属性的 protected set—— 日常开发最高频用法
• 场景:属性对外只读,但允许子类内部修改。比如角色等级、学生的学籍状态,外部只能查看,子类的升级、转职方法可以修改。
• 对比:private set 只有当前类能改;protected set 是当前类 + 所有子类都能改,权限更贴合继承体系。
举个生活例子:学生的学籍状态,对外只能查看(公开读),只有教务处(父类)和班主任(子类)能修改,普通同学(外部代码)改不了,这时候就适合用 protected set。
2.多态
一、什么是多态(通俗定义)
同一个行为,不同对象有不一样的实现效果。
游戏场景举例:所有角色都有「释放技能」这个行为,但战士、法师、弓箭手的技能完全不同。
• 父类角色:统一规定“释放技能”这个动作
• 子类战士:重写技能=近战挥砍
• 子类法师:重写技能=远程火球
• 子类弓箭手:重写技能=射箭
同一个方法名CastSkill(),不同角色调用,效果不一样,这就是多态。
二、实现多态的基础语法:virtual + override
1. virtual:写在父类方法前面,代表这个方法允许子类重写
2. override:写在子类方法前面,代表重写父类标记virtual的方法
示例如下
三、多态真正的核心用法(父类变量接收子类对象)
这是多态最关键的价值,也是游戏开发高频写法:
父类类型的变量,可以存放任意一个它的子类实例。
核心好处
你不需要单独创建战士数组、法师数组,只用一个Character数组,就能管理所有类型角色,一套代码统一调用技能,新增职业只需要新建子类,不用改动原有逻辑。
四、补充:base.方法() 在重写里的作用
重写时如果想保留父类原本的逻辑,再追加子类专属效果,用base.CastSkill()调用父类原方法:
五、硬性规则(必记)
1. 父类不加virtual,子类绝对不能用override重写
2. 重写的方法:方法名、返回值、参数列表必须和父类完全一致
3. 访问权限不能变:父类是public,子类重写也必须public
(前天晚上起来拉肚子没睡好,昨天下午休息少学了会)