1

我是一名 Java 程序员,正在学习 Go 编程。到目前为止,我真的很喜欢这种语言。比 Java 多很多。

但有一件事我有点困惑。Java 有接口,因为类只能从一个类继承。既然 Go 允许多重继承,那么接口的意义何在?

4

4 回答 4

12

多态性

接口使函数能够具有“占位符”参数,该参数可以将不同的结构作为参数。例如,如果结构体 Man、Woman、Child 实现接口 Human,则带有参数 Human 的方法可以将结构体 Man、Woman、Child 中的任何一个作为参数。因此,接口参数可以“变形”为作为参数传递的任何结构,只要它实现了接口中定义的所有函数。

这很重要,因为接口是在 Go 中实现多态性的唯一方法,因为它没有继承。因此,如果 Man “扩展” Human(通过将其作为匿名字段),则任何使用 Human 作为参数的方法都无法将 Man 作为参数。

我的困惑源于这样一个事实,即继承也是在 Java 中实现多态性的一种方式,我认为这里也是如此。我站纠正!

于 2013-08-05T03:29:56.533 回答
9

Go 中的接口与 Java 中的接口非常不同。

在 Java 中,一个类必须正式同意实现一个接口:

public class Foo implements iFoo

在 Go 中,用户类型通过简单地实现接口。

然后,函数或属性可以定义预期的内容:

func DoSomething(r io.Reader) {
    buf := make([]byte, 128)
    n, err := r.Read(buf)
    ...
}

DoSomething函数可以传递任何实现Read在接口中找到的函数的东西io.Reader,而无需知道或关心接口。调用者有责任确保它传入了实现接口的东西。这是在编译时检查的。

我们可以更进一步。我们可以定义自己的接口:

type MyInterface interface {
    io.Reader // Include Reader interface
    Seek(int) error // Include my own function
}
func DoSomething(r MyInterface) {
    buf := make([]byte, 128)
    n, err := r.Read(buf)
    ...
}

Go 的不同之处还在于它没有对象类型。任何用户声明的类型,无论是基于整数、字符串、结构、数组、切片、通道等,都可以附加方法。

Go 也没有你通常习惯的典型的类继承,但它确实有一些非常接近的东西。

重新声明的类型:

type Num int

func (n Num) Print() {
    print(n)
}

type Number Num

func (n Number) Print() {
    Num(n).Print()
}

匿名字段:

type Foo struct {
    sync.Mutex
}

func main() {
    f := Foo{}
    f.Lock()
    // ...
    f.Unlock()
}
于 2013-08-05T06:32:59.383 回答
1

如果超类型 X 是一个接口,那么维护代码的人会立即知道它没有方法实现。如果超类型 Y 是一个抽象类,那么维护代码的人必须检查是否有方法实现。所以这是一个文档/维护/可读性的事情。

于 2013-08-04T23:20:18.980 回答
0

类可以从多个类文件继承和实现。

除非我误解了:

public class MyClass extends MySuperClass implements MyInterface, MySecondInterface

接口的重点是允许一个完全抽象的类。如此抽象以至于没有定义一个方法。当我需要创建几个具有相同基本结构的抽象类时,我会使用接口。然后,我将能够创建扩展抽象类的类的实例,而抽象类又将实现接口。

这是通过接口java.util.Collection和一些类似java.util.ArrayListjava.util.Stack实现该接口的类来完成的。通过这种方式,您可以将各种列表项存储在一个集合中。这就是为什么ArrayList有一个方法addAll(Collection<? extends E> c)

您可以说这就像与更简单的对象向后兼容。

于 2013-08-05T00:58:51.050 回答