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

C#如何在预定义接口方法中使用受保护类方法?强制实现类继承MonoBehaviour

接口与MonoBehaviour兼容问题解决方案

能否在接口中直接使用GetComponentsInChildren<T>()?

不能。接口本身不继承任何类,也不包含MonoBehaviour的方法实现,所以在接口的私有方法ChangeState里直接调用GetComponentsInChildren<T>()会触发编译错误——接口无法识别该方法的定义。

强制实现类继承MonoBehaviour的两种方案

方案1:改用继承MonoBehaviour的抽象类(推荐)

将原接口替换为继承自MonoBehaviour的抽象类,这样所有子类必须继承MonoBehaviour,同时可以把通用逻辑封装在抽象类中,子类仅需实现必要的抽象属性:

public abstract class EquipableBehaviour : MonoBehaviour
{
    protected abstract string EquipedText { get; }
    protected abstract string EquipText { get; }

    protected void ChangeState(bool equipe, string name)
    {
        if ((!equipe && ShopData.GetInstance().IsPurchased(name)) || equipe)
        {
            string message = equipe ? EquipedText : EquipText;
            foreach (var button in GetComponentsInChildren<Button>())
            {
                if (button.tag == "PriceButton")
                    button.enabled = !equipe;
            }
            foreach (var text in GetComponentsInChildren<TextMeshProUGUI>())
            {
                if (text.name == "PriceText")
                    text.text = message;
            }
        }
    }
}

子类实现示例:

public class ShopItem : EquipableBehaviour
{
    protected override string EquipedText => "已装备";
    protected override string EquipText => "装备";
}

这种方式既保证了子类必须继承MonoBehaviour,又避免了重复代码,是Unity场景下最常用的做法。

方案2:在接口中声明依赖方法(不推荐)

如果坚持使用接口,可以在接口内声明需要用到的GetComponentsInChildren<T>()方法,强制实现类(必须是MonoBehaviour)提供该方法的包装实现:

public interface IEquipe
{
    protected abstract string EquipedText { get; }
    protected abstract string EquipText { get; }
    // 声明依赖方法
    protected abstract T[] GetComponentsInChildren<T>() where T : Component;

    private void ChangeState(bool equipe, string name)
    {
        if ((!equipe && ShopData.GetInstance().IsPurchased(name)) || equipe)
        {
            string message = equipe ? EquipedText : EquipText;
            foreach (var button in GetComponentsInChildren<Button>())
            {
                if (button.tag == "PriceButton")
                    button.enabled = !equipe;
            }
            foreach (var text in GetComponentsInChildren<TextMeshProUGUI>())
            {
                if (text.name == "PriceText")
                    text.text = message;
            }
        }
    }
}

实现类示例:

public class ShopItem : MonoBehaviour, IEquipe
{
    protected string EquipedText => "已装备";
    protected string EquipText => "装备";

    protected T[] GetComponentsInChildren<T>() where T : Component
    {
        // 直接调用MonoBehaviour的原生方法
        return base.GetComponentsInChildren<T>();
    }
}

这种方式需要每个实现类重复编写方法包装,代码冗余度高,仅在必须使用接口的场景下考虑。


内容的提问来源于stack exchange,提问作者SEGMK

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 02:48:34