使用接口作为泛型方法的类型参数

时间:2012-11-28 20:35:46

标签: c# generics unity3d

我正在使用C#开发Unity3d游戏,我们在很多情况下需要访问int health的特定成员(例如GameObject)。我们使用以下代码执行此操作:

GameObject obj;
if(obj.GetComponent<Player>() != null) {
    obj.GetComponent<Player>().health--;
}
else if(obj.GetComponent<Robot>() != null) {
    obj.GetComponent<Robot>().health--;
}
// more painful code

我想要做的是让所有这些类实现IHealth之类的接口,然后执行obj.GetComponent<IHealth>().health--;。这可能吗?我环顾四周,看起来我不能将接口用作类型参数。

4 个答案:

答案 0 :(得分:2)

事实证明这并不容易,也许不是一个好主意。问题是GetComponent<T>期望类型参数T派生自Component(当然,Unity不会记录此内容)。我需要使RobotPlayer等等都来自一个抽象类,它本身继承自Component(通过MonoBehaviour),并包含有关健康和其他的信息。领域。我怀疑这是值得的;它可能导致其他地方的代码混乱。

答案 1 :(得分:0)

正如SLaks所指出的那样,接口作为泛型类型参数是完全可以接受的。如果您的问题是通过界面访问某个字段,那么我建议您只需将字段更改为属性即可。如果由于某种原因你绝对必须保留该字段,只需提供一个隐式实现接口的包装属性。如果问题是字段和属性具有完全相同的名称(包括大小写),则可以显式实现接口:

public interface IHealth { int Health { get; set; } }

// Change to a property
public class Ogre : IHealth { public int Health { get; set; } }

// Casing is different, so interface can be implemented implicitly
public class Player : IHealth {
    int health;
    public int Health { get { return health; } set { health = value; } }
}

// Name collision with Pascal casing, so implement explicitly
public class Robot : IHealth {
    int Health;
    int IHealth.Health { get { return Health; } set { Health = value; } }
}

// Later
GameObject obj;
var o = obj.GetComponent<IHealth>();
if (o != null) o.Health--;

答案 2 :(得分:0)

我认为您有一个基本的设计问题,因为您的消费代码需要了解每种类型。如果你采取相同的行动,无论类型如何,那么只需使用好的'多态:

public class Player: IHealth {}

public class Robot: IHealth {}

取代一堆if语句,从GetComponent中删除泛型参数并让它返回一个IHealth对象:

public IHealth GetComponent()
{
    // return IHealth object here
}

在您的主叫代码中:

obj.GetComponent().DecreaseHealth();

答案 3 :(得分:0)

为什么不只有一个组件Health。然后将其附加到GameObject,在任何需要运行状况的脚本上都有RequiresComponent注释,然后通过GetComponent<Health>();获取它(将其缓存在私有变量中的同一对象脚本中)

如果您有多个“统计信息”始终在一起,您可以更轻松地使用

public class Status : MonoBehaviour
{
    public float health;
    public float armor;
}

我发现团结一致,这是一个令人惊讶的常见“问题”。不确定这是否是一个问题因为这个想法可以真正帮助解决一些问题...