Return子class在父类型的方法中

Return child class in a method of parent type

我正在为某些对象使用组件系统(就像 Unity 中的组件一样)。每个组件都继承自 class Component。然后对象有一个组件列表。

我要实现的是 GetComponent() 方法。它 returns 类型为 T 的组件(如果它存在),否则它 returns 为空。假设一个对象具有 Renderer 组件。我希望能够在 Renderer 中调用 Draw 方法 class:

Object.GetComponent<Renderer>().Draw();

问题是,当我调用此函数时,我得到的是父项 class(类型:组件)而不是子项 class。因此,当我尝试上面的代码时 ^^ 我得到了错误; 'Component' 不包含 'Draw' (...)

的定义

代码:

internal abstract class GameObject : Object
{
    //Props
    public string name;
    public GameObject? parent;
    public Transform transform 
    {
        get 
        {
            return (parent == null) ? transform : parent.transform;
        }
        private set 
        {
            transform = value;
        }
    }

    public bool isActive = true;

    private List<Component> components = new List<Component>();

    //Constructor
    public GameObject(string name, GameObject? parent = null)
    {
        this.name = name;
        
        transform = new Transform(this);
        components.Add(transform);

        this.parent = parent;
    }

    public void AddComponent(Component component)
    {
        components.Add(component);
    }

    //Method that is not working properly
    public Component GetComponent<T>()
    {
        foreach (Component component in components)
        {
            if (typeof(T) == component.GetType())
                return component;
        }
        return null;
    }
}

}

方法的return值需要为T

public T GetComponent<T>()
{
    // your code
}

GetComponent<Renderer>().Draw() 是 2 个语句

  1. GetComponent<Renderer>()
  2. Draw()

这样写:

// 'component' is of type 'Component' here, not 'Renderer'
var component = GetComponent<Renderer>();
component.Draw();

很明显为什么它不适用于您当前的代码以及为什么它适用于更新的代码。


P.S 我个人也会添加一个约束以确保我们只能 GetComponent<T> 使用实际上是组件的类型,例如:

public T GetComponent<T>() where T : Component
{

}

使用 where 我们强制编译时检查此方法只能用继承自 Component

的类型调用

而不是 returning Component、return T。此外,使用 is 进行类型检查和转换:

public T GetComponent<T>() where T : Component
{
    foreach(var component in components)
    {
        if(component is T value) return value;
    }
    return default;
}

顺便说一句,如果您有两个相同类型的组件怎么办?您可能要考虑在此处使用 Linq 的 OfType<T>() 而不是 foreach.