与C#泛型,T,抽象有点混淆?

时间:2018-09-23 09:38:39

标签: c# oop unity3d generics abstraction

我是Unity的C#游戏开发商。我有可收集的管理系统。

CollectableManager

import { PopulateComponents } from './populate-components';
@NgModule({
  declarations: [(...) PopulateComponents],

CollectableParent

public List<CollectableParent<Collectable>> collactableParentsList;

SpawnPointDefinedCollectableParent

public class CollectableParent<T> : CollectableRelatedMonoBehaviour where T : Collectable

可收集

public class SpawnPointParentDefinedCollectableParent<T> : CollectableParent<T> where T : Collectable

Collectable_Money

public abstract class Collectable : CollectableRelatedMonoBehaviour, IHasPlayableSound

CollectableParent_Money

public class Collectable_Money : Collectable

问题

当T被定义为“ Collectable_Money”时,CollectableManager中的

“ collactableParentsList”不接受public class CollectableParent_Money : SpawnPointParentDefinedCollectableParent<Collectable_Money> 作为项目,它是从“ Collectable”派生的。如果我这样做SpawnPointParentDefinedCollectableParent<Collectable_Money>,它将被接受为列表中的项目。

1 个答案:

答案 0 :(得分:2)

这里的问题是,即使Collectable_MoneyCollectable的子类,也不会使SpawnPointParentDefinedCollectableParent<Collectable_Money>成为{{ 1}}。

使用通用接口可以解决此问题。如果我们将CollectableParent<Collectable>更改为接口,并通过CollectableParent<T>修饰符在T中将其定义为协变。 (您尚未提供out的定义,但还需要将其转换为接口):

CollectableRelatedMonoBehaviour

如果您随后将列表定义为:

public interface ICollectableParent<out T> : ICollectableRelatedMonoBehaviour where T : Collectable

然后,您可以成功向其中添加public static List<ICollectableParent<Collectable>> collectableParentsList; 类型的项目。

此处的关键部分是SpawnPointParentDefinedCollectableParent<Collectable_Money>接口在ICollectableParent<T>中是协变的。这样就可以传递一个实现T的实例,该实例中期望有ICollectableParent<Collectable_Money>

ICollectableParent<Collectable>中将接口定义为协变确实会引入一些限制,特别是(并且(如用于指示协方差的T修饰符所暗示的那样),类型out必须仅用于接口方法的返回值。例如:

T

您可以在此处详细了解协方差及其逆(协方差):Difference between Covariance & Contra-variance