当有时我想要任何“;T”;

本文关键字:任何 我想要 | 更新日期: 2023-09-27 17:58:38

我正在制作一个关于工厂的游戏。工厂里到处都是装着东西的板条箱。有时会有包含板条箱的仓库,工人需要在板条箱中寻找可用的某些类型的物品(例如,工人可能会调用一个函数,询问"任何仓库中都有装有食物的板条箱吗?",如果有,他会去捡它并把它移到某个地方。

用Generics定义"Crate"answers"Furniture"类(Depot从中继承)以指定它们包含的对象类型似乎非常有用。下面是我的Crate课程和Furniture课程的片段,然后是我正在努力学习的Depot课程:

public class Crate<I> : Item 
    where I : Item
{
}
public abstract class Furniture<I>
    where I : Item
{
}
public class Depot : Furniture<Crate<???>>
{
    //...
}

泛型在这里很有用,因为我可以编写搜索方法,比如:

public I FindItem<I,F>
 where I:Item
 where F:Furniture<I>
{
    //pseudocode
    //foreach (furniture f in the factory);
    //if (f is F) foreach (I i in f)
    //if (i.IsAvailable) return i;
    //return null;
}

现在,我的问题是,与大多数其他家具不同,Depots可以拿走里面有任何东西的板条箱(例如食品板条箱和原材料板条箱)。但我不能只指定Crate(Item),因为它会打乱我的搜索算法——寻找Crates of Food会返回null,因为它只包含Crates of Items。

我应该保留Crate的泛型,但废弃StorageFurniture的泛型,并使我的搜索算法稍微长一点(即搜索所有Furniture,而不仅仅是那些包含正确类型项目的Furniture),还是有办法解决这个问题?

当有时我想要任何“;T”;

考虑为Crate able对象创建一个根类或接口:

public class Crate<I> : Item 
    where I : Item
{
    private int capacity;
    private List<I> contents;
    //... and so on
}
public interface ICrateable{
// define common features such as name, ID, description etc here
}
public class Shirt: ICrateable{
// implement interface
}

public class DepotSlot : StorageFurniture<Crate<ICrateable>>
{
    // now you can add any Crate<XYZ> here
}

如果你正在处理Crate-s,那么只有用它们做一些常见的事情才有意义——打开它们、关闭它们、在它们上贴标签、丢弃它们、将它们装载到卡车上、卸载它们等等。所有这些常见功能都可以在根(abstract?)类或接口中抽象。

如果你对板条箱没有任何预定义的操作,你不妨让它们成为oject,并放弃泛型

如果你的游戏在你的商店里是"自包含的",这样改变基本类型和重新编译所有东西就不会是一个过度的负担,我建议在你的基本"GameObject"类型中有许多虚拟方法,并有一个字段(通过"flags"枚举)指示哪些方法将对给定对象执行某些操作,这可能是有利的。如果一个人有一个游戏对象列表,并想对该列表中与该动作相关的所有对象执行一些动作(例如,炸弹爆炸,一个人想"损坏"爆炸范围内的所有可损坏物品),无条件调用一个所有对象都通用的虚拟方法(即使是那些它什么都不做的对象)比测试每个对象是否实现了接口并在对象上调用该接口更快

在某些情况下,通过允许系统避免在虚拟方法调用之前做一些工作,使字段指示哪些类型的调用与对象相关可以提高性能。例如,如果测试一个字段会发现一个对象不会用TakeBombDamage调用做任何事情,那么就不必浪费时间来计算对象将受到的损坏程度。

如果采取将虚拟方法添加到基类以支持某些但不是所有对象中都存在的功能的方法,则可以最大限度地减少执行运行时类型转换的需要。这将反过来减少对泛型的需求。"厨房水槽基类"方法在基类更改很麻烦的情况下并不好,但在性能很重要的情况下可能会有所帮助,特别是对于存在合理默认值的行为(例如,如果"FlashingStrobe"游戏对象在附近的对象上调用NoticeFlashingStrobe,那么不关心闪光灯的对象可能在这种方法中明智地什么都不做)。