我不确定这些问题应该是两个单独的问题还是一个问题,但在我看来,这个问题分为两部分 - 如何使用接口?我有两个挣扎:
接口的方法是全局范围的:如果我有接口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的包。
答案 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{}
}
我不知道这是否是一个不好的做法,可能在某些情况下需要重新设计而不是这样做。