我是一名Java程序员,学习在Go中编程。到目前为止,我非常喜欢这种语言。比Java更多。
但有一件事我有点困惑。 Java具有接口,因为类只能从一个类继承。由于Go允许多重继承,接口有什么意义?
答案 0 :(得分:11)
多态性
接口使函数具有“占位符”参数,该参数可以将不同的结构作为参数。例如,如果结构Man,Woman,Child实现接口Human,那么带参数Human的方法可以将任何结构Man,Woman,Child作为参数。因此,只要接口参数实现了接口中定义的所有函数,接口参数就可以“变形”为作为参数传递的任何结构。
这很重要,因为接口是在Go中实现多态性的唯一方法,因为它没有继承。因此,如果Man'扩展'Human(通过将其作为匿名字段),任何使用Human作为参数的方法都不能将Man作为参数。
我的困惑源于这样一个事实,即继承也是在Java中实现多态性的一种方式,我也认为这也是这种情况。我的立场得到了纠正!
答案 1 :(得分: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()
}
答案 2 :(得分:1)
如果超类型X是一个接口,那么维护代码的人立即知道它没有方法实现。如果超类型Y是一个抽象类,那么维护代码的人必须检查是否存在方法实现。所以它是文档/维护/可读性的东西。
答案 3 :(得分:0)
类可以从多个类文件继承和实现。
除非我误解了:
public class MyClass extends MySuperClass implements MyInterface, MySecondInterface
接口的要点是允许完全抽象的类。如此抽象,没有定义一个方法。 当我需要创建几个具有相同基本结构的抽象类时,我会使用一个接口。然后,我将能够创建扩展抽象类的类的实例,而抽象类又实现接口。
这是通过接口java.util.Collection
完成的,而某些类如java.util.ArrayList
和java.util.Stack
实现了该接口。这样,您可以将所有类型的列表项存储在集合中。这就是ArrayList
有addAll(Collection<? extends E> c)
方法的原因。
你可以说它就像是向后兼容更简单的对象。