2014-03-06 15 views
3

對於全部實現相同接口的一組類,假定一個或多個類具有不屬於接口定義的其他方法。當我創建這些對象時,使用接口是否有訪問這些方法的方法?還是我必須創建每個單獨的對象而不使用接口?如何訪問不屬於接口定義的方法? (同時仍然對接口進行編程)

class Program 
{ 
    static void Main(string[] args) 
    { 
     ITextProcessor processor = new FileProcessor(); 
     string result = processor.ReadText(); 
     processor.SaveText(result); 


     ITextProcessor processorTest = new FileProcessorTest(); 
     processorTest.testMethod() // unavailable 

    } 
} 


class FileProcessor : ITextProcessor 
{ 
    public string ReadText() 
    { 
     // read in text from a 
     // file and return it 

     return Console.ReadLine(); 
    } 

    public void SaveText(string processedText) 
    { 
     // write processedText out to file. 
     Console.WriteLine(processedText); 
    } 
} 

class FileProcessorTest : ITextProcessor 
{ 
    public string ReadText() 
    { 
     // read in text from a 
     // file and return it 

     return Console.ReadLine(); 
    } 

    public void SaveText(string processedText) 
    { 
     // write processedText out to file. 
     Console.WriteLine(processedText); 
    } 

    public void testMethod() 
    { 
     //I want to be able to access this method 
    } 
} 

interface ITextProcessor 
{ 
    string ReadText(); 
    void SaveText(string processedText); 
} 
+0

您必須創建具體的實現對象而不是接口,或者將接口實例轉換爲該實現對象(並檢查當然不能如此投射的實例)。無論哪種情況,您都已經打破了界面提供的抽象。這聽起來像你需要重新思考你的抽象,而不是試圖繞過它們。 – David

+3

閱讀Liskov的Substition原理 - 它破壞了接口的全部觀點,以檢查具體類的未定義在接口上的任意方法。如果你發現自己這樣做了,你可能需要重新審視你的設計。 –

+0

那麼,如果物體都非常相似,但它們之間的差異很小,那麼最好的解決方案是什麼?使他們有資格使用通用界面,但有變化。 – erotavlas

回答

4

你不能 - 使用接口的全一點是,你知道實施者具有方法,除非它被接口聲明,否則你不可能知道它。

可能通過嘗試轉換爲具體實現之一併在成功時調用方法來解決它;然而,這也違背了這個觀點,因爲接口應該從使用它們的類中抽象出這些具體實現(並且這不會「仍然編程到接口」)。

請注意:如果使用接口的類需要將它用於未在接口中聲明的內容,那麼使用的接口是否正確?

你可能會考慮的一件事是,或許你的調用類需要的不僅僅是這個接口。也許它需要其中一個代替:

public interface ITestableTextProcessor : ITextProcessor 
{ 
    void TestMethod(); 
} 

public class FileProcessorTest : ITestableTextProcessor {...} 

當然,這是否合適(或者甚至可行)取決於你在做什麼。

1

是的,這是可能的,但不是desiderable:

ITextProcessor processor = new FileProcessorTest(); 

//what if you have multiple implementations of ITextProcessor with custom methods each? 
if (processor is FileProcessorTest) { 
    ((FileProcessorTest)processor).testMethod(); 
} 
+0

但是,他沒有編程到界面。他的問題有資格,「而仍然編程接口。」 – Servy

1

你可以試試這個:

class Program 
{ 
    static void Main(string[] args) 
    { 
     ITextProcessor processor = new FileProcessor(); 
     string result = processor.ReadText(); 
     processor.SaveText(result); 

     ITextProcessor processorTest = new FileProcessorTest(); 
     if (processorTest is FileProcessorTest) 
     { 
      ((FileProcessorTest)processor).testMethod(); 
     } 
    } 
} 

如果你不想做這種檢查或知道的代碼,你有什麼情況的話,也許它更容易直接分配類的類型:

FileProcessorTest processorTest = new FileProcessorTest(); 
processorTest.testMethod(); 
1

你不能這樣做。接口在那裏是一個「承諾」,實現它的類將提供所有已聲明的方法。如果您打算將派生類添加到派生類中,那麼它就是而不是接口的一部分 - 它是特定於該特定類的內容。

因此,如果您想使用額外的方法,則必須將該對象作爲該特定的類進行投射。

如果你聲明它是一個接口,那麼你將只能訪問接口中的方法 - 多餘的將被隱藏,直到你投射。

換句話說:不能使用一個接口,以便調用,這不是在接口中定義的,因爲這會破的SOLID principlesL另一方法

class Program 
{ 
    static void Main(string[] args) 
    { 
     ITextProcessor processor = new FileProcessor(); 
     string result = processor.ReadText(); 
     processor.SaveText(result); 


     ITextProcessor processorTest = new FileProcessorTest(); 
     // cast processorTest as the specific type to access the extra method 
     ((FileProcessorTest)processorTest).testMethod() 

    } 
} 
+0

我想我現在明白了,謝謝。 – erotavlas

1

其中指出

objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program

但如其他答案中所述,您可以投射界面變量ble對象,但這並不建議,尤其是當你從某個接口繼承很多對象類型時

+0

擴展方法怎麼樣?怎麼沒有人提到他們?他們似乎符合我的要求,但我不確定 – erotavlas

+0

擴展方法是一個非常好的語法糖意味着沒有魔法將通過添加它們來完成沒有這不能解決您的問題 –

+0

你是對的,我剛剛讀完MSDN文章,他們不是我想要實現的。 – erotavlas