C# Unity3D:如何让基类变量公开但在子类中隐藏?
嘿,我明白你现在卡在这个有点反常规的访问权限需求上了——想让父类CProgressBar的两个变量对外(比如其他业务类)保持公开可访问,但子类ProgressBar自己的内部代码里却要把它们当成私有成员、不能直接碰,对吧?结合Unity的场景,我来给你拆解下可行的思路,毕竟常规的C#继承规则确实不太支持这种“父类公开子类私有”的直接实现:
先理清核心矛盾
在C#的继承体系里,父类的public成员会被子类自动继承,且子类拥有完全的访问权限——所以严格意义上无法做到“父类public,子类中强制私有”。但我们可以通过代码设计来达到近似的效果,满足你的需求:
方案1:用私有字段+公开属性隔离(推荐)
把父类的两个核心变量(比如关联的RawImage和进度值)设为private字段,然后通过public属性对外暴露读写权限。这样一来:
- 外部类可以通过属性正常访问/修改这些值
- 子类因为字段是
private,无法直接操作底层变量,只能通过父类提供的属性或protected方法来交互(如果允许的话)
举个Unity适配的代码例子:
// 父类 CProgressBar using UnityEngine; using UnityEngine.UI; public class CProgressBar : MonoBehaviour { // 私有字段:子类完全无法访问 private RawImage _fillRawImage; private float _currentProgress; // 公开属性:外部类可自由访问 public RawImage FillRawImage { get => _fillRawImage; set { _fillRawImage = value; UpdateProgressVisual(); } } public float CurrentProgress { get => _currentProgress; set { _currentProgress = Mathf.Clamp01(value); UpdateProgressVisual(); } } // 留给子类扩展的protected方法,而非直接暴露变量 protected virtual void UpdateProgressVisual() { if (_fillRawImage == null) return; _fillRawImage.uvRect = new Rect(0, 0, _currentProgress, 1); } }
子类ProgressBar的代码里,你只能通过父类的protected方法扩展逻辑,完全碰不到底层的私有变量:
public class ProgressBar : CProgressBar { [SerializeField] private Animation _progressAnim; protected override void UpdateProgressVisual() { // 先执行父类的基础逻辑 base.UpdateProgressVisual(); // 子类自己的扩展:播放进度变化动画 _progressAnim.Play(); // 这里无法直接访问 _fillRawImage 或 _currentProgress,完美符合你的需求 } }
方案2:用组合替代继承(彻底隔离)
如果你的子类ProgressBar不需要严格继承CProgressBar的所有行为,只是需要复用它的功能,可以用组合代替继承:让ProgressBar内部持有一个CProgressBar实例,对外转发需要公开的接口,但自己的代码里完全不直接操作CProgressBar的变量。
代码示例:
public class ProgressBar : MonoBehaviour { [SerializeField] private CProgressBar _internalProgressBar; // 对外暴露父类的属性,转发调用 public RawImage FillRawImage => _internalProgressBar.FillRawImage; public float CurrentProgress { get => _internalProgressBar.CurrentProgress; set => _internalProgressBar.CurrentProgress = value; } // 子类自己的业务逻辑 public void TriggerProgressEffect() { // 这里完全碰不到 _internalProgressBar 的内部变量,彻底隔离 Debug.Log("Progress changed, triggering effect!"); } }
这种方式虽然打破了继承关系,但能完全实现“外部可访问,子类内部不可碰”的需求,适合不需要继承多态特性的场景。
为什么常规方案没解决你的问题?
之前的方案可能只是让你用protected修饰变量,但这会让子类能直接访问,不符合你“子类中保持私有”的要求;或者让你用private但没搭配公开属性,导致外部也访问不了。上面的两个方案都是围绕“隔离子类对父类核心变量的直接访问”来设计的,应该能解决你的痛点。
内容的提问来源于stack exchange,提问作者MutantSFox

