我有以下情况:
interface IBaseReader{
string Header {get; set;}
string CurrentRow {get; set;}}
class BaseReader: IBaseReader{
......}
interface ICustomReader{
string Header {get; set;}
string Delimiter {get; set;}}
class CustomReader :BaseReader, ICustomReader{
......}
在文件处理类中,我使用这个ICustomReader来知道来自BaseReader的派生实例是否是ICustomReader,如果它比我知道它包含分隔符并且我可以验证它。
IBaseReader _reader;
if(_reader is ICustomReader)
{
var items = (_reader as ICustomReader).Header.Split((_reader as ICustomReader).Delimiter);
//split the current row and header by delimiter and check if it is ok
}
我的朋友们说编写这样的代码是不行的,因为我们正在检查当前表示为IBaseReader的实例是否是ICustomReaderthat出现在派生类中,这意味着基类应该知道有关派生类的内容。我一般我们为此开发了更好的解决方案。但我只是想知道究竟是什么打破了,在这种情况下什么是正确的解决方案,如果我们不能在类之间移动属性?
谢谢!
答案 0 :(得分:2)
检查其他界面以查看属性是否可用时没有任何问题。问题是您有两个单独的接口,其Header
属性不代表两个单独的属性。如果IDerived
继承IBaseReader
:
interface IDerived : IBaseReader {
string Delimiter {get; set;}}
或者它是一个完全独立的界面,仅与分隔符有关:
interface IHasDelimiter {
string Delimiter {get; set;}}
然后,无需转换到新界面来访问Header
属性,因为您已在当前类型的_reader
上使用它:
var items = _reader.Header.Split((_reader as ICustomReader).Delimiter);
答案 1 :(得分:1)
当创建层次结构的主要原因是使代码可重用时,基本上将基类IBaseReader
耦合到派生类ICustomReader
。
现在,只要您想从IBaseReader
派生新界面,即使您不需要,也必须包含ICustomReader
。
答案 2 :(得分:1)
这类代码存在问题的一个主要问题是脆弱性。
如果更改ICustomReader
,则只需要重新编译该类以及任何引用它的内容。这是因为只有它和明确使用它的任何东西都应该真正了解它的内部工作(例如它的属性)。
如果您认为BaseReader
在一个程序集中而ICustomReader
在另一个程序集中,那么对ICustomReader
的任何更改(例如它不再有分隔符)那么它将导致你的BaseReader无缘无故地破解。
如果您在BaseReader
上有一个名为Validate
或类似的虚拟方法,那么可以在当前进行类型特定验证的地方调用它。在基类中,如果没有要进行验证,则此方法可能无效。然后在ICustomReader
的具体实现中,您可以覆盖验证以执行您想要执行的任何特定验证。通过这种方式,基类只知道它是什么以及它的接口是什么以及它的行为是什么以及其他任何事情都会被子类的特定实现所担心,这些子类知道它们做什么以及需要在它们上验证什么。
这有一个额外的好处,如果你添加ICustomReader2
,那么你只需要编写该类,而不必去BaseReader
添加额外的逻辑。想象一下,如果你有50个自定义阅读器,那么代码会对所有if语句检查特定类型的程序造成多么混乱。这个混乱代码的解决方案是将你的长行ifs重构为单独的方法,每种类型一个。然后很容易想到为什么不将这些方法放在子类上。
这样做的另一个主要原因是使维护更简单。对您的代码不熟悉的人可能想知道ICustomReader
的验证在哪里?那么,它当然就在那一堂课上。基类不是你所期望的,所以如果它存在的话就会让人迷惑。
良好的代码结构是一个相当庞大且重要的主题,我试图提出一些非正式的论据,可能会帮助您直观地了解为什么这是一个坏主意。如果你想谷歌获取更多信息,一个有用的术语将是"紧密耦合" http://en.wikipedia.org/wiki/Coupling_(computer_programming)#Disadvantages列出了其他一些缺点。