簡體   English   中英

接口作為參數

[英]Interfaces as parameters

在什么情況下有人會將接口作為參數傳遞(或接收)? 這真的是一件有用的事情還是一種奇特的做事方式?

這是一個非常有用的東西。

例如,采用任何 LINQ擴展方法 他們不關心傳遞給他們的是什么,只要它實現IEnumerable<T> 我們的想法是,它們都可以應用於使用foreach循環可以枚舉的任何內容。

想象一下,如果他們都要求你傳遞T[]數組或List<T>對象,那將是多么無意義的限制。


這只是一個非常簡單的例子。 讓我們假裝LINQ擴展不存在(如果我使用的是.NET 2.0,這實際上是一種可能性)並且我想編寫一個Sum方法。

我可以像這樣寫:

public static double Sum(List<double> values)
{
    double sum = 0.0;
    foreach (double value in values)
    {
        sum += value;
    }
    return sum;
}

這一切都很好,但在這里注意一些事情:我編寫了一個方法來獲取List<double> ,這是一個具有比這個代碼所依賴的更多功能的類。 它在哪里使用Insert 它在哪里使用RemoveAt FindAll Sort 不,這不是必需的。 那么這個方法真的有必要通過List<double>嗎?

而且,說我有double[] 從理論上講,我應該能夠將其作為values參數彈出,因為我所做的就是使用foreach枚舉它; 但由於我輸入的values List<double> ,要將double[]傳遞給我的Sum方法,我必須這樣做:

double sum = Sum(new List<double>(myArray));

這只是一個完全不必要的新對象,我構建它只是為了調用真正應該能夠首先處理我的原始對象的代碼。

通過編寫將接口作為參數的方法,您可以使代碼更靈活,更強大,並且您可以避免在調用代碼時施加不適當的限制( 給我一個X,即使我可以很容易地使用Y )。

最簡單的方法是,它是關於編程接口而不是實現。 比方說,我有一個方法,我想做某事,例如

public void MakeNoise(IAnimal animal)
{
  animal.MakeNoise();
}

我不在乎具體實現是什么,我只知道無論傳入什么,我都可以調用MakeNoise()。 我編程到一個接口,而不是一個實現。

public class Dog : IAnimal
{
  public void MakeNoise()
  {
    Console.WriteLine("Woof");
  }
}

public class Cat : IAnimal
{
  public void MakeNoise()
  {
    Console.WriteLine("Meow");
  }
}

接口編程是OOP的核心方面,你會發現它們非常有用。

每當你需要抽象時。

一個很好的例子是.NET Framework中的IEnumerable<T>IQueryable<T>接口。 它們允許您編寫可用於List<T >, Dictionary<TKey, TValue>甚至T[]擴展方法。

例如,您也可以使用依賴注入。 在ASP.NET MVC中,通常使用存儲庫進行數據訪問:

public class MyClassRepository
{
    public MyClass GetById(int id)
    {
        // Some Implementation
    }
}

public class MyController
{
    private MyClassRepository _repo;

    public class MyController() : base(new MyClassRepository()) { }

    public class MyController(MyClassRepository repo) { _repo = repo; }
}

現在,如果你想模擬用於單元測試的存儲庫...你就是骨頭。 沒有簡單的方法。 接口來了!

public interface IMyClassRepository
{
    public MyClass GetById(int id);
}

public class MyClassRepository : IMyClassRepository
{
    public MyClass GetById(int id)
    {
        // Some Implementation
    }
}

public class MyController
{
    private IMyClassRepository _repo;

    public class MyController() : base(new MyClassRepository()) { }

    public class MyController(IMyClassRepository repo) { _repo = repo; }
}

現在通過引入接口,我們可以自由地模擬IMyClassRepository但是我們認為適合於測試目的。 通常,這涉及一個具有指定行為的簡單模擬對象,以產生可靠的結果

接口非常有用。

它們有助於解耦代碼 - 例如,如果使用IList接口並將其傳遞給方法並在方法中使用它,則可以傳入實現此接口的任何集合,無論它是否在BCL中。

如果使用設計模式方法 ,接口很有意義的一個領域。

例如, 觀察者模式代理模式訪客模式等。 您可能可以選擇不使用接口,但我想你會很快決定代碼變得更清晰(如更模塊化,關注點分離)而不是非接口代碼。 在這些情況下,它只是有助於促進更好的代碼。

多態性!

它們可以幫助您編寫不歧視某些類的代碼,因為它們不會從特殊的基類繼承。 您的職能將是平等機會執行者。

暫無
暫無

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

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