Suggestion: Allow interfaces to constrain what types can implement them #9734
Replies: 6 comments 8 replies
-
|
How would you handle state? Why can't GameObject be an interface itself? That way the rest of the interfaces could inherit from IGameObject. |
Beta Was this translation helpful? Give feedback.
-
|
You can try to use generic method void Damage<T>(T destuctibleObject)
where T : GameObject, IDestructible
{ } |
Beta Was this translation helpful? Give feedback.
-
public interface IGameObject {
IGameObject Instance { get; }
}
public interface IDestructible : IGameObject {
void Destroy();
}
public abstract class DestructibleObject : IGameObject, IDestructible {
IGameObject IDestructible.Instance => this;
public abstract void Destroy();
} |
Beta Was this translation helpful? Give feedback.
-
You later clarify that what you desire is for Whilst multiple inheritance could be implemented - C++ supports it, for example - there is a vanishingly small chance that the .NET runtime and C# teams would ever add support for it to the runtime and C#, respectively. Perhaps instead, you could turn the problem on its head and avoid inheritance altogether by using interfaces: public interface IDestructible
{
public void Destroy();
}
public interface IGameObject
{
public void DoSomething();
}
public interface IDestructibleObject : IGameObject, IDestructible;
public void Damage(IDestructibleObject obj)
{
obj.DoSomething();
obj.Destroy();
} |
Beta Was this translation helpful? Give feedback.
-
|
#399 might be an interesting alternative to what you need. Specifically the intersection types. |
Beta Was this translation helpful? Give feedback.
-
|
The usual pattern I use for restricting interface inheritors is public abstract class GameObject {}
// Use this for APIs like Scene.DoAllThings(IGameThing[] things);
public interface IGameThing { void DoThing(); }
// Use this for inheritance
public interface IGameThing<T> : IGameThing where T : GameObject, IGameThing<T> {}
public abstract class GameThing : GameObject, IGameThing<GameThing>
{
public abstract void DoThing();
} |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Consider the following code:
The code above doesn't compile, because an interface can't inherit from a class. But, suppose it could specify that only a certain type can implement it. Now, you would know that every
ISharedFeaturesobject is guaranteed to be aBaseClassor class that derives fromBaseClass. This would mean that you could make derived classes that share common functionality (using an interface), but that don't inherit from the same ancestors. Let me illustrate this with a more concrete problem:The code above works, but there is a problem. Not all pickables are destructible, and not all destructibles are pickable. We cannot make our
DestructiblePickableObjectinherit from bothDestructibleObjectandPickableObject, so, now if there is code that only accepts a destructible object, we cannot pass it ourDestructiblePickableObjectobject, for example. We can solve this by using an interface, likeIDestructible, and implement it in bothDestructibleObjectand inDestructiblePickableObjectclasses. Now, code that requires a destructible object can just require anIDestructible, like this:However, now we have a different problem: the
IDestructibleis not guaranteed to be aGameObject. And that is what my suggestion of allowing an interface to inherit from a class tries to solve. IfIDestructibleinherits fromGameObject, onlyGameObjectand its derived classes could implement it, and it would be guaranteed to be aGameObjectto any of its consumers.Right now, we can solve this in a hacky way like this:
So, now, you could consume it like this:
But the hacky solution above is not pretty and not practical. It would be much easier if
IDestructiblewas declared like this:Maybe this is somewhat of a niche use case, but I already had to deal with that problem a few times.
What are your thoughts on this suggestion? Do you think it would be even possible to implement reliably in the language? And what could go wrong?
Beta Was this translation helpful? Give feedback.
All reactions