我有一个自定义类(我们称之为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-instance和list / data-property提供不同的数据类型。但是通用示例中的T将是相同的,只允许这样:
MyClass<Foo> foo = new MyClass<Foo>;
foo.list = new List<MyClass<Foo>>;
foo.list中的每个项目将再次具有可能属于不同类型的列表。当我编译MyClass
时,我不知道列表/数据属性中将包含哪些数据类型或者将会有多少级别。如何构建这种灵活的结构?
答案 0 :(得分:1)
泛型旨在允许编译器对类型使用情况进行检查,它们还提供了一些非常好的额外好处。
使用泛型无法实现您所描述的内容,如果每次使用可能不同类型的列表更新list
时,泛型都无法帮助您。
但是,如果这些类型中的每一种都共享一个共同的基本类型或共享一个公共接口,那么您可以将其用作列表的T
,并允许您使用它们。
但是,如果MyClass
的每个实例只允许一种类型的MyClass<?>
列表,那么您可以修改MyClass
:
public class MyClass<T, TList>
{
private List<MyClass<T, TList>> list;
private T data;
}
答案 1 :(得分:1)
只用一个课程就无法达到这个目标。您必须为每个级别的子级构建一个通用基类,一个基类用于最低级别而不包含子级,一个派生类用于每个层次级别。
基类看起来像这样:
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()
}
}
}
};
答案 2 :(得分:0)
在MyClass中添加第二种类型。
public class MyClass<T, G>
{
private List<MyClass<G, T>> list;
private T data;
}
这假设您不关心列表中嵌套列表的类型。
但是你能否详细说明你的代码的实用程序,因为很难用抽象数据来解决这个问题。
答案 3 :(得分:0)
我正在尝试在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.
}
这显然是不完整的,但我希望它能给你一些想法。