依赖于接口

时间:2016-08-23 18:08:16

标签: go interface

我不确定这些问题应该是两个单独的问题还是一个问题,但在我看来,这个问题分为两部分 - 如何使用接口?我有两个挣扎:

接口的方法是全局范围的:如果我有接口A和接口B都实现相同的方法Foo,但具有不同的参数或返回类型,我无法同时从同一类型实现。例如,我在一个接口中有GetBytes()方法,返回类型为[]字节,另一个([]字节,错误)我应该如何克服这个问题?

我遇到的另一个问题是当我尝试定义接口时,接口A有一个方法返回在同一层中定义的接口B.现在,如果我想创建一个实现A的对象,如果我返回实现B的结构,那么就不够聪明地推断出这个方法实现了A中的方法并且它迫使我创建对B的依赖。这似乎完全打败了接口工作的方式在第一位。我该如何避免这个问题?

例如,如果我有:

type B interface {
    Bar()
}

type A interface {
    Foo() B
}

以下结构:

type b_impl struct{}

func (b b_impl) Bar() {}

type a_impl struct{}

foo方法

func (a a_impl) Foo() b_impl {}

不满足接口A,我需要做到:

func (a a_impl) Foo() B {}

,它依赖于声明B的包。

2 个答案:

答案 0 :(得分:2)

第一个问题: 当您想要执行不同的任务时,您需要创建不同的函数名称。让我们看看strconv包中的标准库如何在那里解决问题:https://golang.org/pkg/strconv/#pkg-index

查看那里附加函数的不同声明。每种不同类型都有功能。

因此,如果您期望FooInt功能,您的界面也应该是FooInter,...

第二个问题:作为一个小例子。如果要使用io.Writer界面,则无需导入整个io包。完全可以将Writer声明复制到您自己的包中。如果你这样做,每个io.Writer实现都会自动实现你自己的Writer接口。

在阅读其他评论后,您可能会遇到不同的情况:

假设有一个包a和b,接口a.A和b.B.如果出现以下情况:

using (var con = new SqlConnection(connectionString))
{
    con.Open();

    using (var cmd = new SqlCommand(
        @"INSERT INTO etudient (IDetudient, [nom etudient], value)
          VALUES (@ID, @Name, @Variable)", con))
    {
        cmd.Parameters.AddWithValue("@ID", text_id.Text);
        cmd.Parameters.AddWithValue("@Name", text_name.Text);
        cmd.Parameters.AddWithValue("@Variable", variable);
        cmd.ExecuteNonQuery();
    }
}

你必须为a.A编写一个实现,然后你需要导入包b。但这会使你的二进制文件不大,因为你总是需要导入包a,这取决于b。

答案 1 :(得分:0)

要实现接口,您需要具有完全相同的方法名称和签名。表示签名必须具有相同的类型

看起来很奇怪,但这两个签名不相同:

Foo() B
Foo() b_impl {}

b_impl实现B无关紧要。

要克服声明导入B包的需要,可以使用匿名类型。这样,编译器就不需要方法签名的特定类型。

type A interface {
    Foo() interface{Bar()}
}

也可以写成嵌入B

type A interface {
    Foo() interface{B}
}

仍然,a_impl必须具有相同的签名,因此它还需要返回一个匿名接口。您还可以在B的程序包中声明相同的a_impl接口,并将其嵌入匿名接口中。

package impl

type B interface {
    Bar()
}

type b_impl struct{}

func (b b_impl) Bar() {}

type a_impl struct{}

func (a a_impl) Foo() interface{B} {
    return b_impl{}
}

我不知道这是否是一个不好的做法,可能在某些情况下需要重新设计而不是这样做。