【问题标题】:What's the differences between Go and Java about interface? [closed]Go和Java在接口方面有什么区别? [关闭]
【发布时间】:2017-02-17 08:47:24
【问题描述】:

最近有人问我一个问题,Golang 和 Java 关于 interface 的区别是什么?

我知道存在一些“语法糖级别”的差异,我感兴趣的是底层的任何东西,比如 Golang 和 Java 如何实现接口?最大的不同是什么?哪个效率更高?为什么?

任何人都可以发布有关此主题的博客链接或源代码吗?源代码更好。

谢谢。

【问题讨论】:

标签: java go interface


【解决方案1】:

Go Data Structures: Interfaces by Russ Cox

Go 的接口——静态的、编译时检查的、询问时动态的 对于
Go 的接口让你可以像在纯粹的情况下一样使用鸭子类型 像 Python 这样的动态语言,但编译器仍然很明显 错误,例如传递一个带有 Read 方法的对象的 int 预期的,或者喜欢用错误的数量调用 Read 方法 论据。
不过,接口并不局限于静态检查。你可以检查 动态地是否一个特定的接口值有一个额外的 方法。

接口值
带有方法的语言通常属于两个阵营之一:准备 所有方法调用的表都是静态的(如在 C++ 和 Java 中),或者做 每次调用的方法查找(如在 Smalltalk 及其许多模仿者中, 包括 JavaScript 和 Python)并添加精美的缓存来实现 通话高效。 Go 介于两者之间:它有方法表 但在运行时计算它们。我不知道 Go 是不是第一个 使用这种技术的语言,但它肯定不是一种常见的。
接口值表示为两个字对,给出一个指针 有关存储在接口中的类型的信息和指向的指针 相关的数据。将 b 分配给类型的接口值 Stringer 设置接口值的两个字。

接口值中的第一个词指向我所说的 接口表或 itable(读作 i-table;在运行时 来源)。 itable 以一些关于类型的元数据开头 涉及,然后成为一个函数指针列表。请注意, itable对应的是接口类型,不是动态类型。
接口值中的第二个字指向实际数据,在 本例是 b 的副本。

Go 的动态类型转换意味着它对于 预计算所有可能的 itables 的编译器或链接器:也有 许多(接口类型,具体类型)对,大多数都不需要。 相反,编译器为每个 具体类型,例如 Binary 或 int 或 func(map[int]string)。除其他外 元数据,类型描述结构包含一个列表 该类型实现的方法。同样,编译器生成一个 (不同)每个接口类型的类型描述结构,如 纵梁;它也包含一个方法列表。接口运行时 通过查找接口中列出的每个方法来计算 itable 具体类型的方法表中的类型的方法表。运行时 生成后将itable缓存起来,使这个对应关系 只需要计算一次。

方法查找性能
Smalltalk 和许多跟随它的动态系统执行了一个 每次调用方法时查找方法。为了速度,很多 实现在每个调用站点使用简单的单项缓存,通常 在指令流本身中。在多线程程序中,这些 缓存必须小心管理,因为多个线程可能在 同一个呼叫站点同时进行。即使比赛已经结束 避免,缓存最终会成为内存争用的来源。

因为 Go 有静态类型与动态类型的提示 方法查找,它可以将查找从调用站点移回 值存储在接口中的点。


How does Go interface dispatch work?

接口变量上的方法调度与 vtable 相同 调度。
当具体类型第一次遇到接口类型时,它会构建一个 指向 vtable 的哈希表条目。第二次及以后 相同类型的分配将执行更便宜的哈希查找 找到 vtable。但是方法调度本身总是 相当于一个 vtable 查找。


规格:Interface types

更多详情见:Go: What's the meaning of interface{}?


这里有两个有趣的 Go 接口用例: Why are interfaces needed in Golang?


错误类型是接口类型:How to compare Golang error objects


计算 4 种不同形状的面积:圆形、正方形、矩形和三角形:
Explain Type Assertions in Go


在 Go 中,您不需要做任何特别的事情,例如 Java 关键字 implements 来实现接口,在 Go 中,您的类型只需具有正确签名的方法就足够了。

这是代码(在The Go Playground 上试试):

package main

import "fmt"

type Work struct {
    Name string
}

func (t Work) String() string {
    return "Stringer called."
}

func main() {
    w := Work{"Hi"}
    fmt.Println(w)
}

输出:

Stringer called.

规格:type Stringer,参见source

type Stringer interface {
        String() string
}

Stringer 由任何具有 String 方法的值实现,该方法 定义该值的“本机”格式。使用 String 方法 将作为操作数传递的值打印到任何接受 字符串或打印到未格式化的打印机,例如 Print。


另见:

Why can't I assign a *Struct to an *Interface?
Meaning of a struct with embedded anonymous interface?
Embedded Interface
Golang: what's the point of interfaces when you have multiple inheritence

【讨论】:

  • 谢谢兄弟,但我认为这种差异是语法糖级别的,我想知道编程语言/编译器/运行时级别的差异。诸如方法表、方法查找、运行时类型检查等...
  • @fding 查看新编辑。我希望这会有所帮助。
猜你喜欢
  • 1970-01-01
  • 2014-04-03
  • 1970-01-01
  • 2012-05-17
  • 1970-01-01
  • 2014-03-17
  • 1970-01-01
  • 1970-01-01
  • 2016-09-30
相关资源
最近更新 更多