泛型类中的泛型集合
本文关键字:集合 泛型 泛型类 | 更新日期: 2023-09-27 18:07:40
我有一个自定义类(我们称之为MyClass
),它看起来像这样:
public class MyClass
{
private List<MyClass> list;
private object data;
}
然而,我想摆脱object
属性,而是使用泛型类。像这样:
public class MyClass<T>
{
private List<MyClass<T>> list;
private T data;
}
然而,我需要这样的行为:
MyClass<Foo> foo = new MyClass<Foo>;
foo.list = new List<MyClass<Bar>>;
所以我需要能够有不同的数据类型的foo实例和列表/数据属性在foo。但是通用示例中的T将是相同的,并且只允许这样:
MyClass<Foo> foo = new MyClass<Foo>;
foo.list = new List<MyClass<Foo>>;
foo中的每一项。List将再次拥有一个可能是不同类型的列表。当我编译MyClass
时,我不知道列表/数据属性中会有什么数据类型,也不知道会有多少个级别。我该如何构建这种灵活的结构?
泛型被设计成允许编译器执行类型使用检查,它们还提供了一些漂亮的额外好处。
你所描述的不能用泛型实现,如果每次你用一个可能不同类型的列表更新list
,那么泛型不能帮助你。
然而,如果这些类型共享一个公共基类型或共享一个公共接口,那么你可以使用它作为列表的T
,这将允许你使用它们。
如果MyClass
的每个实例只允许MyClass<?>
的一种类型的List,那么你可以这样修改MyClass
:
public class MyClass<T, TList>
{
private List<MyClass<T, TList>> list;
private T data;
}
仅用一个类是无法实现这个目标的。您必须为每个带子的级别构建一个泛型基类,为没有子的最低级别构建一个基类,并为每个层次结构级别构建一个派生类。
基类看起来像这样:
public class MyClass<TData>
{
public TData Data { get; set; }
}
public class MyClass<TData, TDataChildren, TChildren> : MyClass<TData>
where TChildren : MyClass<TDataChildren>
{
public List<TChildren> List { get; set; }
}
每个级别的派生类看起来像这样:
public class Level0 : MyClass<Foo, Bar, Level1> { }
public class Level1 : MyClass<Bar, Fubar, Level2> { }
public class Level2 : MyClass<Fubar> { }
用法:
var root = new Level0();
root.Data = new Foo();
root.List = new List<Level1>
{
new Level1()
{
Data = new Bar(),
List = new List<Level2>
{
new Level2()
{
Data = new Fubar()
}
}
}
};
在MyClass中添加第二个类型。
public class MyClass<T, G>
{
private List<MyClass<G, T>> list;
private T data;
}
这是假设你不关心列表中嵌套列表的类型。
但是您能详细说明一下您的代码的实用性吗?因为仅用抽象数据很难判断。
我正试图在c++中实现一个非常类似的事情,现在我遇到了同样的问题。模板的问题在于它们是强类型的,MyClass<foo>
被视为与MyClass<bar>
完全不同且不相关的类型。
我现在玩的是创建一个抽象类,上面有纯虚拟方法,如GetInt
, GetDouble
, GetBool
, GetString
。然后,我想有一个模板化的Add
,它将实例化适当的具体类并将其添加到我的向量。我不确定它是否会工作,但它是沿着这些行:
class Data
{
public:
template<typename T> Add(const std::string& key, const T& val)
{
Data* pData = NULL;
//test the type using std::numeric_limits to figure out which concrete
//type to use.
m_mapValues[key] = pData;
}
protected:
virtual int GetInt() const = 0;
virtual unsigned int GetUINT() const = 0;
virtual std::string GetString() const = 0;
//blah blah more types that you want to handle
private:
std::map<std::string,Data*> m_mapValues;
};
class UINTData : public Data
{
//implement pure virtual methods.
}
这显然是不完整的,但我希望它能给你一些想法。