Oop 什么时候应该使用接口?

Oop 什么时候应该使用接口?,oop,interface,Oop,Interface,我知道接口没有主体,只有方法定义。但是我应该什么时候使用接口呢?如果我为某人提供一组没有主体的接口,为什么他们会觉得需要编写函数主体?他们最好编写自己的抽象类,其中包含抽象方法 编辑: 我想当你是团队的一部分时,界面的使用会更多。假设团队A为某个东西编写了代码,他们想看看是否需要调用某个方法。已完成或未完成名为getRecords()的。这将帮助团队B编写提供给他们的接口主体,团队B必须保持方法名称相似,以便团队A的代码运行 只是一个想法。我可能错了。我认为接口对单个开发人员没有用处 编辑: 谢

我知道接口没有主体,只有方法定义。但是我应该什么时候使用接口呢?如果我为某人提供一组没有主体的接口,为什么他们会觉得需要编写函数主体?他们最好编写自己的抽象类,其中包含抽象方法

编辑: 我想当你是团队的一部分时,界面的使用会更多。假设团队A为某个东西编写了代码,他们想看看是否需要调用某个方法。已完成或未完成名为getRecords()的。这将帮助团队B编写提供给他们的接口主体,团队B必须保持方法名称相似,以便团队A的代码运行

只是一个想法。我可能错了。我认为接口对单个开发人员没有用处

编辑:
谢谢大家的回答。根据大家的回答,我认为接口在制作类似API的东西时更有用。

接口比抽象类更好,因为可以实现多个接口,并且只能从一个抽象类继承

因此,您可以:

class MyRow extends AbstractRow implements ISearchable, ISortable
{

}

另外,在StackOverflow中搜索其他类似的问题,如

使用接口的一个原因是一个类何时将实现多个接口。抽象类不能做到这一点


例如,一个处理鼠标移动和按键的类将实现(虚构的)IMouseMove和IKeyPress接口。

此外,使用接口简化单元测试。为了测试依赖于接口的类,并且只要使用某种依赖注入,就可以创建实现依赖接口的存根类,或者可以使用模拟引擎。

要添加到前面的答案中,接口通过允许您将基于接口的模拟对象注入到代码中来帮助您进行单元测试,允许您模拟特定场景,还允许您将单元测试隔离到特定组件,而不依赖外部组件


例如,假设您有一个业务逻辑类,该类使用数据逻辑类从数据源检索数据,然后对其进行处理。通过为随后继承的数据逻辑类创建接口,您可以基于该接口创建该类的模拟/伪实例,并将其注入正在进行单元测试的业务逻辑类中。可以定义模拟实例以期望某些方法/属性调用、在某些点引发异常、返回有效输出等。这意味着,单元测试可以更快/可能更可靠地运行,因为它们不依赖于可用的底层数据源/实际上不必连接到它。您正在将单元测试隔离到一个特定的代码单元。

乍一看,抽象类和接口似乎很容易理解。既然还可以提供一些基本实现,为什么只提供一个接口呢?经过调查,你会发现还有更多

也就是说,使用接口有很多原因。你可以找到一篇关于这些差异的像样的博客文章

这样说,考虑一个事实,你可以创建一个接口(一个“契约”,它表示你的类肯定支持某些调用/方法签名调用),但是你只能提供一个抽象类。还要考虑这样一个事实,即您可以创建一个抽象类,该类还实现一个或多个接口,并从此继承。这不是边缘案件。这实际上在API中非常频繁地执行,这意味着高扩展性


查看我给你指出的博客文章,你应该彻底了解何时使用它们以及为什么要使用它们。我还强烈推荐一本好书,如微软出版社的《通过C#的CLR》。你会学到很多

在Java和C等语言中,接口为类提供了一种方式。也就是说,一个类可以满足多个契约——它可以表现为多个不同的类型,一个类型的类可以替换另一个类型的类。在其他语言中,这也可以由提供,但这种方法有各种缺点。然而,让一个类表现为多个类型并不是使用接口的最常见动机

通过编程到接口而不是类,您还可以将程序与特定实现解耦。这使得用一个类实现替换另一个类实现更加容易。这在编写单元测试时特别有用,您可能希望将一些重量级类实现与轻量级类交换。如果您的程序只需要一个接口类型,并且重量级对象和模拟对象都实现了所述接口,那么它们很容易替换

也可以考虑一个简单的java示例,我说有一个程序,它显示屏幕上的数据页。最初,我希望它从数据库或XML文件中获取数据。如果我编写的程序使用接口,我可以这样定义一个接口:

public interface PageDatasource {
    public List<Page> getPages();
}
公共接口页面数据源{
公共列表getPages();
}
并像这样使用它:

PageDatasource datasource = // insert concrete PageDatasource implementation here
List<Pages> pages = datasource.getPages();
display(pages);
PageDatasource datasource=//在此处插入具体的PageDatasource实现
List pages=datasource.getPages();
显示(页);
然后,我可以编写遵循此接口的单独数据库和XML实现:

public class DatabasePageDatasource implements PageDatasource {
    public List<Page> getPages() {
        // Database specific code
    }
}

public class XmlPageDatasource implements PageDatasource {
    public List<Page> getPages() {
        // XML specific code
    }
}
公共类DatabasePageDatasource实现PageDatasource{
公共列表getPages(){
//数据库特定代码
}
}
公共类XmlPageDatasource实现PageDatasource{
公共列表getPages(){
//特定于XML的代码
}
}
因为我使用了一个接口,我现在可以互换地使用实现(数据库或XML),而无需更改程序中请求页面数据的部分。XML和数据库实现可能做完全不同的事情,但我的程序所关心的只是提供p
public abstract class A {
    public void myFunc() {
        //do some work
    }
}

public class B : A {
    private void someOtherFunc() {
        base.myFunc();
    }
}

public class Z {
    public void exampleFunc() {
        //call public base class function exposed through extending class:
        B myB = new B();
        myB.myFunc();

        //explicitly cast B to A:
        ((A) myB).myFunc();

        //'A' cannot be created directly, do implicit cast down to base class:
        A myA = new B();
        myA.myFunc();
    }
}
public class Z {
    public void exampleFunc() {
        C myC = new C();
        //these two calls both call the same function:
        myC.myFunc();
        ((IExampleInterface1)myC).myFunc();

        D myD = new D();
        //hmmm... try and work out what happens here, which myFunc() gets called?
        //(clue: check the base class)
        myD.myFunc();

        //call different myFunc() in same class with identical signatures:
        ((IExampleInterface1)myD).myFunc();
        ((IExampleInterface2)myD).myFunc();
    }
}

interface IExampleInterface1
{
    void myFunc();
}

interface IExampleInterface2
{
    void myFunc();
}

public class C : IExampleInterface1
{
    public void myFunc()
    {
        //do stuff
    }
}

public class D : A, IExampleInterface1, IExampleInterface2
{
    void IExampleInterface1.myFunc()
    {
        //this is called when D is cast as IExampleInterface1
    }

    void IExampleInterface2.myFunc()
    {
        //this is called when D is cast as IExampleInterface2
    }
}
class PersonA implements Librarian {
    public void IssueBook(){...}
    public void ReIssueBook(){...}
    public void ReturnBook(){...}

    //Other person related tasks...
}   
public interface IFoodEstablishmentService
{
    Task<int> AddAsync(FoodEstablishment oFoodEstablishment);
    FoodEstablishment SelectByFoodEstablishmentId(long id);
    Task<int> UpdateAsync(FoodEstablishment oFoodEstablishment);
    Task<int> DeleteAsync(FoodEstablishment oFoodEstablishment);
}
public class FoodEstablishmentService : IFoodEstablishmentService
{
    public async Task<int> AddAsync(FoodEstablishment oFoodEstablishment)
    {
       // Insert Operation
        return result;
    }

    public FoodEstablishment SelectByFoodEstablishmentId(long id)
    {
        // Select Logic
        return oFoodEstablishment;
    }

    public async Task<int> UpdateAsync(FoodEstablishment oFoodEstablishment)
    {
        // Update Logic
        return result;
    }

    public async Task<int> DeleteAsync(FoodEstablishment oFoodEstablishment)
    {
        // Delete Logic
        return result;
    }

}
IFoodEstablishmentService oFoodEstablishmentService =  new FoodEstablishmentService();
FoodEstablishment oFoodEstablishment = // Input might be from views;
oFoodEstablishmentService.AddAsync(oFoodEstablishment);
FoodEstablishmentService oFoodEstablishmentService =  new FoodEstablishmentService();
FoodEstablishment oFoodEstablishment = // Input might be from views;
oFoodEstablishmentService.AddAsync(oFoodEstablishment);
public class FoodEstablishmentQueueService : IFoodEstablishmentService
{
    public async Task<int> AddAsync(FoodEstablishment oFoodEstablishment)
    {
       // Insert Queue Operation
        return result;
    }

    public FoodEstablishment SelectByFoodEstablishmentId(long id)
    {
        // Select Queue Logic
        return oFoodEstablishment;
    }

    public async Task<int> UpdateAsync(FoodEstablishment oFoodEstablishment)
    {
        // Update Queue Logic
        return result;
    }

    public async Task<int> DeleteAsync(FoodEstablishment oFoodEstablishment)
    {
        // Delete Queue Logic
        return result;
    }
}
IFoodEstablishmentService oFoodEstablishmentService =  new FoodEstablishmentQueueService();
FoodEstablishment oFoodEstablishment = // Input might be from views;
oFoodEstablishmentService.AddAsync(oFoodEstablishment);
public FoodEstablishment[] SortFoodEstablishment(FoodEstablishment[] list)
{
    foreach(var oFoodEstablishment in list)
    {
    // some logic
    }
    return sortedList;
}
FoodEstablishment[] list = new FoodEstablishment[]{ //some values }
var listSorted = oFoodEstablishmentService.SortFoodEstablishment(list);
List<FoodEstablishment> list = //some values;
var listSorted = oFoodEstablishmentService.SortFoodEstablishment(list);
public IEnumerable<FoodEstablishment> SortFoodEstablishment(IEnumerable<FoodEstablishment> list)
{
    foreach(var oFoodEstablishment in list)
    {
    // some logic
    }
    return sortedList;
}