首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在接口中实现接口

在接口中实现接口
EN

Stack Overflow用户
提问于 2014-01-31 11:56:40
回答 1查看 215关注 0票数 1

我正在编写一些导入文件的代码,这些代码将根据描述文件布局的模板导入分隔文件或固定宽度文件。

我创建了一个接口IFileTemplate:

代码语言:javascript
复制
public interface IFileTemplate
{
   string Name { get; set; }
   bool IgnoreEmptyLines { get; set; }
}

它由DelimitedFileTemplate类和FixedWidthFileTemplate类使用。

我还有一个接口,用于指定组成模板的每个列:

代码语言:javascript
复制
public interface IFileTemplateColumn
{
   int ID { get; set; }
   string Name { get; set; }
   bool Ignore { get; set; }
}

然后,DelimitedTemplateColumn类和FixedWidthTemplateColumn类使用这个接口。

由于DelimitedFileTemplate和FixedWidthFileTemplate类都有一个列列表,所以我已经将该列表作为IFileTemplate列的成员:

代码语言:javascript
复制
List<IFileTemplateColumn> Fields { get; set; }

我的问题是,当我在DelimitedFileTemplate和FixedWidthFileTemplate类中实现列表时,例如:

代码语言:javascript
复制
public class FixedWidthFileTemplate : IFileTemplate
{
   public int ID { get; set; }
   public string Name { get; set; }
   public List<FixedWidthFileTemplateColumn> Fields { get; set; }
}

如果我尝试用List<DelimitedFileTemplateColumn>List<FixedWidthFileTemplateColumn>实现List<DelimitedFileTemplateColumn>List<FixedWidthFileTemplateColumn>,那么编译器会抱怨它们与List<IFileTemplateColumn>不匹配。

我可以理解这一点,但是在ITemplateInterface中没有列列表似乎是错误的。我能想到的唯一解决办法是让分隔的类和FixedWidth类使用List<IFileTemplateColumn>,并让属性getter将列表转换为分隔的或固定宽度的列列表,但这似乎有一点代码气味。有人能提出更好的方法来做这件事吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-01-31 12:05:56

泛型是解决这个设计问题的合适且无臭味的解决方案:

代码语言:javascript
复制
interface IFileTemplate<T> where T : IFileTemplateColumn
{
    List<T> Fields { get; set; }
}

DelimitedFileTemplate实现了IFileTemplate<DelimitedFileTemplateColumn>等等。

也许文件模板之间的所有差异都可以由IFileTemplateColumn明智地定义,并且您可以简化FileTemplate<IFileTemplateColumn>在每一个FileTemplateColumn类关系中嵌入一个FileTemplate类的情况。

更新

至于工厂方法:IFileTemplate<IFileTemplateColumn> Create:如果假定该方法的使用者能够访问列列表,则方法签名必须包含具体的ColumnTemplate。例如:

代码语言:javascript
复制
DelimitedFileTemplate Create

代码语言:javascript
复制
interface IFactory<T> where T : IFileTemplateColumn
{
    IFileTemplate<T> Create();
}

class DelimitedFactory : IFactory<DelimitedFileTemplateColumn>
{
    IFileTemplate<DelimitedFileTemplateColumn> Create() 
    {
        return new DelimitedFileTemplate();
    }
}

如果该方法的使用者对列表不感兴趣,请引入一个更通用的接口(非常类似于IEnumerable<T> : IEnumerable):

代码语言:javascript
复制
interface IFileTemplate { ... }
interface IFileTemplate<T> : IFileTemplate where T : IFileTemplateColumn
{
    List<IFileTemplateColumn> Columns { get; set; }
}

然后,无论列是什么,IFileTemplate Create()方法都可以返回任何具体的FileTemplate。

我使用过这种泛型,它们可能会传播(在本例中,列层次结构将在FileTemplate层次结构中复制,并可能在工厂层次结构中复制)。有时,这会暴露出设计中的一些缺陷。如果您能够明智地将IFileTemplate层次结构划分为一个基本的参数化FileTemplate类,那么这当然是可行的。这就是我经常使用的方法:定义最小的部分,如果层次结构倾向于重复,算法的某些部分可能会被移动到“最小的部分-类”。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21479533

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档