unity3d C#如何在预定义的接口方法中使用受保护类的方法

ssm49v7z  于 2023-03-19  发布在  C#
关注(0)|答案(3)|浏览(146)

我想做这样的事情:

public interface IEquipe
{
    protected abstract string EquipedText { get; }
    protected abstract string EquipText { get; }
    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;
            }
        }
    }
}

但是GetComponentsInChildren<Button>()是一个来自Monobehavior类的方法,只有当你继承类的时候才能使用它,我能用某种方法使用它或者创建一个语句来强制实现那个接口的类也从Monobehavior继承吗?

sirbozc5

sirbozc51#

你可以使用继承了Monobehavior的类:

public class CustomMonobehavior:Monobehavior
{
       public new T GetComponentsInChildren<T>() => base.GetComponentsInChildren<T>();
}

现在在代码中使用它

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

qltillow2#

如果你坚持使用默认的接口实现(尽管它有不同的用途),那么你可以做的一件事就是在你的接口中定义GetComponentsInChildren<T>的签名,或者更好:为MonoBehaviour方法创建一个接口,您需要频繁使用这些方法,以避免使用相同的签名将它们全部混淆。

public interface IMonoBehaviourOperations
{
    T[] GetComponentsInChildren<T>();
}

public interface IEquipe : IMonoBehaviourOperations
{ 
....
}

这样,从MonoBehaviour继承的类将自动实现GetComponentsInChildren方法。

2ic8powd

2ic8powd3#

您不一定需要强制类继承MonoBehaviour:你只需要确保他们有一个GetComponentsInChildren方法。

public interface IEquipe
{
    protected abstract string EquipedText { get; }
    protected abstract string EquipText { get; }
    protected abstract T[] GetComponentsInChildren<T>(); // <--- add this
    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;
            }
        }
    }
}

任何从MonoBehaviour(或者实际上是any Component)派生的实现IEquipe接口的类都将自动实现GetComponentsInChildren成员,而不需要任何额外的代码。
几个旁注:

  • 这可能是对默认接口方法的误用。请考虑您是否真的希望允许实现IEquipe的类使用它们自己的首选行为覆盖此实现。如果不希望,您可能希望将ChangeState移到一个单独的类中--例如,它可以是静态类中的扩展方法,而不更改使用代码中的任何内容。
  • “Equipe”是一个法语名词,意思是“团队”,而“Equip”是一个英语动词(过去时态“装备”),意思是“提供一个项目”。我猜您打算使用后者,在这种情况下,您可能需要修改拼写。

相关问题