简体   繁体   中英

Return child class in a method of parent type

I am using a component system for certain Objects(just like components in Unity). Each component inheriths from the class Component . The objects then have a list of components.

What I am trying to implement is a GetComponent() method. It returns the component of type T if it exists, otherwise it returns null. Let's say that an Object has the Renderer Component. I want to be able to call the Draw method in the Renderer class:

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

The problem is that when I call this function I get the parent class(of type: Component ) instead of the child class. Because of that, when I try the code above ^^ I get the error; 'Component' does not contain a definition for 'Draw' (...)

Code:

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>();

    //Constructer
    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;
    }
}

}

The return value of the method needs to be T

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

GetComponent<Renderer>().Draw() is 2 statements

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

By writing it like so:

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

It's obvious why it doesn't work with your current code and why it does with the updated one.


PS I'd personally also add a constraint to make sure we can only GetComponent<T> with types that actually are components, like so:

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

}

With the where we're forcing compile time checks that this method can only be called with types that inherit from Component

Instead of returning Component , return T . Also, use is for type checking and casting:

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

BTW, what if you have two components of the same type? You might want to consider using Linq's OfType<T>() here instead of a foreach .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM