You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:40:11