我想问的问题是:
从抽象类内部向下转换继承树(即朝向更专业的类)是可以原谅的,甚至是一件好事,还是它总是一个糟糕的选择,有更好的选择?
现在,为什么我认为它可以用于良好的例子。
我最近在 C# 中从 BitTorrent 协议实现了 Bencoding 。一个足够简单的问题,如何表示数据。我选择这样做,
我们有一个abstract BItem
类,它提供了一些基本功能,包括static BItem Decode(string)
用于将 Bencoded 字符串解码为必要结构的类。
还有四个派生类,、BString
和,表示要编码的四种不同数据类型。现在,这是棘手的部分。和have和accessors 分别允许访问这些数据类型的类似数组的质量。BInteger
BList
BDictionary
BList
BDictionary
this[int]
this[string]
潜在的可怕部分现在来了:
BDictionary torrent = (BDictionary) BItem.DecodeFile("my.torrent");
int filelength = (BInteger)((BDictionary)((BList)((BDictionary)
torrent["info"])["files"])[0])["length"];
好吧,你明白了……哎呀,这对眼睛来说很难,更不用说大脑了。所以,我在抽象类中引入了一些额外的东西:
public BItem this[int index]
{
get { return ((BList)this)[index]; }
}
public BItem this[string index]
{
get { return ((BDictionary)this)[index]; }
}
现在我们可以将旧代码重写为:
BDictionary torrent = (BDictionary)BItem.DecodeFile("my.torrent");
int filelength = (BInteger)torrent["info"]["files"][0]["length"];
哇,嘿presto,更具可读性的代码。但是我是否只是为了将子类的知识暗示到抽象类中而出卖了我的一部分灵魂?
编辑:作为对一些答案的回应,你完全偏离了这个特定问题的轨道,因为结构是可变的,例如我的例子torrent["info"]["files"][0]["length"]
是有效的,但也是如此torrent["announce-list"][0][0]
,两者都将在 90% 的 torrent 文件中在那里。泛型不是要走的路,至少有这个问题:(。点击我链接的规范,它只有 4 个小点。