簡體   English   中英

在接口內實現接口

[英]Implementing interfaces within interfaces

我正在編寫一些用於導入文件的代碼,這些代碼將根據描述文件布局的模板來導入定界或定寬文件。

我創建了一個接口IFileTemplate:

public interface IFileTemplate
{
   string Name { get; set; }
   bool IgnoreEmptyLines { get; set; }
}

DelimitedFileTemplate類和FixedWidthFileTemplate類使用。

我還有一個接口,用於指定組成模板的每一列:

public interface IFileTemplateColumn
{
   int ID { get; set; }
   string Name { get; set; }
   bool Ignore { get; set; }
}

然后, DelimitedTemplateColumn類和FixedWidthTemplateColumn類將使用此接口。

由於DelimitedFileTemplate和FixedWidthFileTemplate類都將具有列列表,因此我將該列表作為IFileTemplate列的成員:

List<IFileTemplateColumn> Fields { get; set; }

我的問題是,當我要在DelimitedFileTemplate和FixedWidthFileTemplate類中實現列表時,例如:

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<IFileTemplateColumn> ,則編譯器會抱怨它們與List<IFileTemplateColumn>不匹配。

我可以理解這一點,但是如果ITemplateInterface中沒有列列表,這似乎是錯誤的。 我能想到的唯一解決方法是讓Delimited和FixedWidth類使用List<IFileTemplateColumn>並將屬性getter將該列表List<IFileTemplateColumn>轉換為定界或固定寬度的列列表,但似乎有點代碼味道。 有人可以建議一種更好的方法嗎?

通用的解決此設計問題的合適方法是:

interface IFileTemplate<T> where T : IFileTemplateColumn
{
    List<T> Fields { get; set; }
}

DelimitedFileTemplate實現IFileTemplate<DelimitedFileTemplateColumn> ,依此類推。

也許文件模板之間的所有差異只能由IFileTemplateColumn合理地定義,並且您可以通過使用FileTemplate<IFileTemplateColumn>來簡化每個模板關系,從而簡化每個事情。

更新

至於工廠方法: IFileTemplate<IFileTemplateColumn> Create :如果該方法的使用者應該能夠訪問列列表,則方法簽名將必須包含具體的ColumnTemplate。 例如:

DelimitedFileTemplate Create

要么

interface IFactory<T> where T : IFileTemplateColumn
{
    IFileTemplate<T> Create();
}

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

如果該方法的使用者對列表不感興趣,請引入一個更通用的接口(類似於IEnumerable<T> : IEnumerable ):

interface IFileTemplate { ... }
interface IFileTemplate<T> : IFileTemplate where T : IFileTemplateColumn
{
    List<IFileTemplateColumn> Columns { get; set; }
}

然后,無論列如何,您的IFileTemplate Create()方法都可以返回任何具體的FileTemplate。

我已經使用了這種泛型用法,它們可能會傳播(在此示例中,Column層次結構將在FileTemplate層次結構中重復,並且可能在工廠層次結構中重復)。 有時,這會揭示設計中的一些缺陷。 如果您能夠將IFileTemplate層次結構合理地切割為一個基本參數化的FileTemplate類,那么這當然是可行的方法。 這就是我經常使用的方式:定義最小的部分,如果層次結構傾向於重復,則算法的某些部分可能可以移至“最小的部分類”。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM