Language agnostic “这对”意味着什么;编程到一个接口;?

Language agnostic “这对”意味着什么;编程到一个接口;?,language-agnostic,oop,interface,Language Agnostic,Oop,Interface,我已经见过几次提到这一点,我不清楚这是什么意思。你什么时候为什么要这样做 我知道接口是做什么的,但我不清楚这一点,这让我觉得我错过了正确使用它们的机会 如果你要做的是: IInterface classRef = new ObjectWhatever() 您可以使用实现IInterface的任何类?你什么时候需要这样做?我能想到的唯一一件事是,如果您有一个方法,并且您不确定将传递什么对象,除了它实现IInterface。我想不出你需要多久做一次 另外,如何编写一个方法来接收实现接口的对象?这可

我已经见过几次提到这一点,我不清楚这是什么意思。你什么时候为什么要这样做

我知道接口是做什么的,但我不清楚这一点,这让我觉得我错过了正确使用它们的机会

如果你要做的是:

IInterface classRef = new ObjectWhatever()
您可以使用实现
IInterface
的任何类?你什么时候需要这样做?我能想到的唯一一件事是,如果您有一个方法,并且您不确定将传递什么对象,除了它实现
IInterface
。我想不出你需要多久做一次


另外,如何编写一个方法来接收实现接口的对象?这可能吗?

您应该研究控制反转:

在这种情况下,您不会这样写:

IInterface classRef = new ObjectWhatever();
你可以这样写:

IInterface classRef = container.Resolve<IInterface>();
public void DoSomethingToAnObject(IInterface whatever) { ... }
这直接插入到“与做特定事情的对象对话”中。上面定义的方法知道对对象的期望,它实现了接口中的所有内容,但它不关心它是哪种类型的对象,只关心它遵守契约,这就是接口

例如,你可能对计算器很熟悉,在你的生活中可能用过不少,但大多数时候它们都是不同的。另一方面,你知道一个标准计算器应该如何工作,所以你可以使用它们,即使你不能使用每个计算器都没有的特定功能

这就是界面之美。您可以编写一段代码,它知道它将获得传递给它的对象,它可以期望从中获得某些行为。它一点也不关心它是什么类型的对象,只关心它支持所需的行为

让我给你举个具体的例子

public interface IPricable
{
    int Price { get; }
}

public interface ICar : IPricable

public abstract class Article
{
    public int Price { get { return ... } }
}

public class Car : Article, ICar
{
    // Price does not need to be defined here
}
我们有一个为windows窗体定制的翻译系统。该系统通过表单上的控件进行循环,并在每个控件中翻译文本。系统知道如何处理基本控件,如-type-of-control-that-has-Text-property和类似的基本内容,但对于任何基本的东西,它都不够

现在,由于控件继承自我们无法控制的预定义类,我们可以做以下三件事之一:

  • 为我们的翻译系统构建支持,以专门检测它使用的控件类型,并翻译正确的位(维护噩梦)
  • 将支持构建到基类中(不可能,因为所有控件都继承自不同的预定义类)
  • 添加接口支持

  • 所以我们做了3号。我们所有的控件都实现了ILocalizable,这是一个接口,它为我们提供了一种方法,能够将“自身”翻译成翻译文本/规则的容器。因此,表单不需要知道它找到了哪种控件,只需要知道它实现了特定的接口,并且知道有一种方法可以调用来本地化控件。

    对接口编程就是说,“我需要这个功能,我不在乎它来自何方。”


    考虑(在Java中,
    List
    接口与
    ArrayList
    LinkedList
    具体类的对比。如果我所关心的是,我有一个包含多个数据项的数据结构,我应该通过迭代访问这些数据项,那么我会选择一个
    列表(这是99%的时间)。如果我知道我需要从列表的任意一端进行固定时间的插入/删除,我可能会选择
    LinkedList
    具体实现(或者更可能的是,使用接口)。如果我知道我需要通过索引进行随机访问,我会选择
    ArrayList
    concrete类。

    当您有一组类似的类时,它使您的代码更易于扩展和维护。我是一个初级程序员,所以我不是专家,但我刚刚完成了一个需要类似东西的项目

    我使用客户端软件与运行医疗设备的服务器对话。我们正在开发此设备的新版本,其中包含一些客户有时必须配置的新组件。有两种类型的新组件,它们不同,但也非常相似。基本上,我必须创建两个配置表单,两个列表类,所有的两个

    我决定最好为每个控件类型创建一个抽象基类,该类将包含几乎所有的实际逻辑,然后派生类型来处理这两个组件之间的差异。但是,如果我不得不一直担心类型的问题,基类就不能对这些组件执行操作(当然,它们可以,但是每个方法中都会有一个“if”语句或开关)


    我为这些组件定义了一个简单的接口,所有的基类都与这个接口通信。现在,当我改变一些东西时,它几乎在任何地方都能“正常工作”,我没有代码重复。

    为了补充现有的文章,当开发人员同时在不同的组件上工作时,有时在大型项目中编写接口代码会有所帮助。您只需预先定义接口并在其他开发人员为您正在实现的接口编写代码时向其编写代码。

    除了消除类之间不必要的耦合之外,使用接口是使代码易于测试的关键因素。通过创建定义类上的操作的接口,可以允许希望使用该功能的类在不直接依赖于实现类的情况下使用该功能。如果以后决定更改并使用不同的实现,则只需更改实例化实现的代码部分。代码的其余部分不需要更改,因为它取决于接口,而不是实现类

    这在创建单元测试时非常有用。在测试的课堂上,你有它
    ArrayList myList = new ArrayList(); // this is bad
    
    List myList = new TreeList();
    
    public ArrayList doSomething(HashMap map);
    
    public List doSomething(Map map);
    
    char charAt(int index)
    int length()
    CharSequence subSequence(int start, int end)
    String toString()
    
    // if I want to add search capabilities to my application and support multiple search
    // engines such as Google, Yahoo, Live, etc.
    
    interface ISearchProvider
    {
        string Search(string keywords);
    }
    
    // if I want to support multiple downloads using different protocols
    // HTTP, HTTPS, FTP, FTPS, etc.
    interface IUrlDownload
    {
        void Download(string url)
    }
    
    // how about an image loader for different kinds of images JPG, GIF, PNG, etc.
    interface IImageLoader
    {
        Bitmap LoadImage(string filename)
    }
    
    interface IZipCodeRepository
    {
        IList<ZipCode> GetZipCodes(string state);
    }
    
    PrintZipCodes(IZipCodeRepository zipCodeRepository, string state)
    {
        foreach (ZipCode zipCode in zipCodeRepository.GetZipCodes(state))
        {
            Console.WriteLine(zipCode.ToString());
        }
    }
    
    Dintf bInst = new Bclass();  
    // now we could call all Dintf functions implemented (defined) in Bclass.
    
    Dintf cInst = new Cclass();  
    // now we could call all Dintf functions implemented (defined) in Cclass.
    
    interface Airplane{
        parkPlane();
        servicePlane();
    }
    
    parkPlane(Airplane plane)
    
    servicePlane(Airplane plane)
    
    public class Fighter implements Airplane {
    
        public void  parkPlane(){
            // Specific implementations for fighter plane to park
        }
        public void  servicePlane(){
            // Specific implementatoins for fighter plane to service.
        }
    }
    
    public class HighFlyer implements Airplane {
    
        public void  parkPlane(){
            // Specific implementations for HighFlyer plane to park
        }
    
        public void  servicePlane(){
            // specific implementatoins for HighFlyer plane to service.
        }
    }
    
    public Class ControlPlane{ 
     AirPlane plane;
     // so much method with AirPlane reference are used here...
    }
    
    JumboJetPlane // implementing AirPlane interface.
    AirBus        // implementing AirPlane interface.
    
    public interface IPricable
    {
        int Price { get; }
    }
    
    public interface ICar : IPricable
    
    public abstract class Article
    {
        public int Price { get { return ... } }
    }
    
    public class Car : Article, ICar
    {
        // Price does not need to be defined here
    }
    
    class Person implements AbstractEmployee, AbstractFriend {
    }
    
    function party() {
        const friend: Friend = new Person("Kathryn");
        friend.HaveFun();
    }
    
    function workplace() {
        const employee: Employee = new Person("Kathryn");
        employee.DoWork();
    }