在Unity中使用GetComponent时通过基类管理派生类?

时间:2017-10-04 14:48:39

标签: c# inheritance unity3d casting

每当我尝试建立一个继承层次结构时,我发现自己一遍又一遍地困在这个场景中。

在当前表单中,我有一个基类,代表我游戏中的所有UI元素。我打电话给这个类,UI_Toggleable。此类具有每个派生类可以设置的枚举属性。以下简要介绍代码的外观:

public class UI_Toggleable 
{

    // The Menu Type enum that all derived classes must define.
    protected UIMenus menuType;

    // Gives any child of this class a toggle function
    // to enable/disable UI when needed.
    public void ToggleUI()
    {
        // Toggle Code
    }

    // Public property Getter - Read Only Access.
    // Only derived classes can define the value of the menu type.
    public virtual UIMenus MenuType
    {
        get { return menuType; }
    }
}

现在,假设一个名为InventoryUI的类派生自Toggleable,我们有以下内容。

 public class  InventoryUI : UI_Toggleable
{

    private void Awake()
    {
        _instance = this;
        menuType = UIMenus.Inventory;
    }

    public override UIMenus MenuType
    {
        get { return menuType; }
    }
}

现在,如果我尝试为这些对象实现管理器,我将需要获取每个派生类的菜单类型。但是,我不想ASSUME UI_Toggleable类的类型。相反,我想要做的是将任何派生类作为UI_Toggleable,然后继续调用MenuType方法以获取其类型。

UI_Toggleable toggleable = GetComponent<UI_Toggleable>();
toggleable.MenuType;

上面的问题是,它会返回基类的MenuType而不是我作为基类检索的派生类。这有点期待,但我想得到派生类的MenuType而不执行以下操作:

if(GetComponent<UI_Toggleable>() is  InventoryUI )
 InventoryUI toggleable = GetComponent< InventoryUI >();
toggleable.MenuType;

上述工作,但它失败了我设置一个与孩子共享类似属性的基类的目的。执行所有这些强制转换和检查只会使代码看起来难以阅读和解耦。

我尝试过的其他事情包括以下内容:

  • 创建定义函数GetMenuType的IMenuType接口。每个派生类都实现了该方法,在我的经理中,我会进行检查if(toggleable is IMenuType)。如果为true,则尝试调用((IMenuType)可切换).GetMenuType。
  • 让MenuType属性getter成为每个派生类必须实现的抽象函数。但与上述情况类似,我仍然需要在尝试调用方法之前进行强制转换检查。
  • 虽然不是我的首选,但MenuType方法并不是虚拟的。

1 个答案:

答案 0 :(得分:3)

您没有正确设置基类的menuType。而不是在派生类的Awake方法中设置它,在构造函数中设置它,如下所示:

public class UI_Toggleable {
    public UIMenus MenuType {get;}
    // Subclasses must pass the correct menuType here
    protected UI_Toggleable(UIMenus menuType) {
        MenuType = menuType;
    }
}
public class  InventoryUI : UI_Toggleable {
    // Pass the proper menu type for storing inside the base class
    public InventoryUI() : base(UIMenus.Inventory) {
    }
}

注意MenuType现在是基类的只读属性,而不是覆盖的虚拟属性。

  

我无法真正使用构造函数。如果我用Awake方法设置它可以接受吗?

从您的代码示例中可以看出,Awake未及时调用abstract,以便基类提供正确的值。在这种情况下,您使用public class UI_Toggleable { public abstract UIMenus MenuType {get;} } public class InventoryUI : UI_Toggleable { public override UIMenus MenuType { get => UIMenus.Inventory } } 仅限getter的属性,如下所示:

get => UIMenus.Inventory

注意: get { return UIMenus.Inventory; }的旧版语法为Check the current OS version, eg : 10.0.XX.X