Question

I'm currently building my own game engine based on Unity's decorator model. I have three classes (SceneStateManager (controls only one Scene at a time) > Scene > SceneLayer > GameObject > Component) that make up the scene hierarchy which all are basically the same except for the name and some smaller, very specific features. (Overriding methods will do it in this case)

All classes are initializable from the parent hierarchy level class type, and control a number of childs. As there is a lot of common functionality shared by the classes, I want to let them derive from a base class which groups the shared features to simplify the code.

The "super base class" (ListJob<T>) is a class that controls the childs, and until now, all of the beforementioned types derive from it to simplify at least that part. So the child handling itself does not need to be included in the code here as it is already working very well.

I now need to get a proper generic signature for the base class all of the scene hierarchy classes are to derive from in the future. My current solution does not compile with this error: http://msdn.microsoft.com/en-us/library/bb384252(v=vs.100).aspx


My current version of the generic signature and the SceneSystemJob class:

public abstract class SceneSystemJob<TItem, TParent> : ListJob<TItem>, IInitializable<TParent>  
    where TItem : IInitializable<SceneSystemJob<TItem, TParent>>
{  
    private TParent _Parent = default(TParent);

    public TParent Parent
    {
        get
        {
            return _Parent;
        }
        protected set
        {
            _Parent = value;
        }
    }

    // Implementation

    public void Initialize(TParent parent)
    {
        this.Parent = parent;
    }
}

SceneStateManager:

public class SceneStateManager // Controls only one Child and does not derive from super base class

Scene:

public class Scene : SceneSystemJob<SceneLayer, SceneStateManager>

SceneLayer:

public class SceneLayer : SceneSystemJob<GameObject, Scene>

GameObject:

public class GameObject: SceneSystemJob<Component, SceneLayer>

Component:

public abstract class Component : Manager, IInitializable<GameObject>

Interface IInitializable:

public interface IInitializable<TParent>
{  
    void Initialize(TParent parent);  
}

If you still need more code, please tell me.

Was it helpful?

Solution

I don't know how to solve your problem other than by starting over with a much simpler system. This seems very over-engineered.

To explain why your code is wrong, look at this greatly simplified version of it:

public interface IInitializable<TParent> { }
public class SceneSystemJob<TItem>  
    where TItem : IInitializable<SceneSystemJob<TItem>>
{ }
public class GameObject : SceneSystemJob<Component> { } // Error here
public class Component : IInitializable<GameObject> { }

The error is that Component cannot be used as TItem. Why not? It seems plausible that this should work:

  • TItem requires that it implement IInitializable<SceneSystemJob<TItem>>.
  • Component implements IInitializable<GameObject>
  • GameObject is a special kind of SceneSystemJob<Component>>
  • Therefore Component meets the criterion of implementing IInitializable<SceneSystemJob<Component>>

The conclusion unfortunately does not follow from the premise unless IInitializable<T> is covariant in T. Since your real implementation has a method which takes in a T, it cannot be covariant in T.

Think about it this way. An IInitializable<T> is like a container that you can put a T into. The constraint says "you need to give me a TItem such that it is a container that I can put any SceneSystemJob<TItem> into." You are giving it a container that you can only put GameObject into. Therefore the constraint is not met.

It's like the constraint says "I need a cage that can contain any animal" and you're handing it an aquarium. Well, that's a cage that can contain any fish, but the constraint doesn't say "I need a cage for some animal, your choice", it says it needs a cage for any animal.

I don't know how you fix this mess you've gotten yourself into other than starting over and not being so excessively generic.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top