【问题标题】:Is there any profits of using Methods rather than Functions?使用方法而不是函数有什么好处吗?
【发布时间】:2019-10-01 06:17:00
【问题描述】:

为了练习围棋,我正在开发“矩阵”结构和相关方法。 我做了很多方法,但我意识到所有这些方法都可以变成函数 我习惯了 C++,在 C++ 中,如果我创建一个参数是类类型的函数,该函数不能使用该类的私有变量(信息隐藏) 但是,当我使用“Go”构建类似的代码时,函数可以访问结构的变量。 所以我不明白 Go 中的方法和函数有什么不同。 使用方法而不是函数是否有任何利润,反之亦然?

第一个是我原来的“矩阵”代码(不是全部) 它使用了一种方法“Tr”。 它没有问题。

package main
import "fmt"

//definition of "Array"
type Array struct{
    component [][]float32
    row int
    col int
}
//constructor of Array, "Ones"; making an array setting all component as one
func Ones(m int, n int) Array{
    var a Array
    a.component = make([][]float32, m)
    a.row=m
    a.col=n
    for i:=0; i<m; i++{
        a.component[i] = make([]float32, n)
        for j:=0; j<n; j++{
            a.component[i][j]=1
        }
    }
    return a
}
//Tr function; find trace of an Array
func (a Array) Tr() float32{
    var sum float32 = 0
    for i:=0; i<a.row; i++{
        sum += a.component[i][i]
    }
    return sum
}

func main(){
    a := Ones(3,3)
    fmt.Println(a.Tr())
}

第二个是另一个类似的代码。 (一切都一样,但“Tr”部分) 它只使用函数。 它也没有问题。

package main
import "fmt"

//definition of "Array"
type Array struct{
    component [][]float32
    row int
    col int
}
//constructor of Array, "Ones"; making an array setting all component as one
func Ones(m int, n int) Array{
    var a Array
    a.component = make([][]float32, m)
    a.row=m
    a.col=n
    for i:=0; i<m; i++{
        a.component[i] = make([]float32, n)
        for j:=0; j<n; j++{
            a.component[i][j]=1
        }
    }
    return a
}
//Tr function; find trace of an Array
func Tr(a Array) float32{
    var sum float32 = 0
    for i:=0; i<a.row; i++{
        sum += a.component[i][i]
    }
    return sum
}

func main(){
    a := Ones(3,3)
    fmt.Println(Tr(a))
}

【问题讨论】:

  • Go 中没有方法之类的东西。只有功能。我想这回答了这个问题。
  • 来自here:“方法是具有特殊接收器参数的函数。”
  • @MarkusWMahlberg 有趣的是,Go 语言规范有关于方法声明、方法表达式、方法值和方法集的部分。
  • @MarkusWMahlberg 我们并不是说方法不是函数,甚至您的引文也说方法是事物,所以说它们不存在是很苛刻的。

标签: function go methods


【解决方案1】:

如果你只是想调用函数或方法,没关系,你可以创建一个带有签名的函数,其中接收者是一个普通的、常规的参数。不会有任何性能损失(如果方法可以是 virtual,但在 Go 中没有虚拟方法)。

一个优势可能是“视觉吸引力”。调用一个方法使其明显属于接收者。如果使用方法,我还发现链式代码更容易理解。

比较这个没有方法的解决方案:

type Circle struct{}
type Point struct{}

func Center(Circle) Point { return Point{} }
func Abs(Point) float64   { return 0 }

func main() {
    var c Circle
    fmt.Println(Abs(Center(c)))
}

Abs(Center(c)) 不是那么直观。但是如果你添加方法而不是使用函数:

func (Circle) Center() Point { return Point{} }
func (Point) Abs() float64 { return 0 }

func main() {
    var c Circle
    fmt.Println(c.Center().Abs())
}

c.Center().Abs() 更容易理解。

如果要实现接口,方法是必须的。如果接口包含一些方法,那么只有具有这些方法的类型才能实现它。参见相关:Why are interfaces needed in Golang? 还应注意,您只能创建定义在同一个包中的方法,因此如果您想从不同的包中“武装”一个类型,则不能“使用”方法。

我将使用方法称为“利润”的一件事是:您不能按名称调用函数,但可以按名称访问和调用方法。详情请见Call functions with special prefix/suffix

【讨论】:

  • 另外,方法的命名空间是定义它们的类型,而不是包命名空间。因此,可以在一个包中定义两个不同的名为 Foo 的方法,但不能定义两个名为 Foo 的函数。
  • @Peter True,但如果需要,我们可以很容易地命名 2 个不同的 Foo 函数 Type1FooType2Foo
猜你喜欢
  • 2016-03-27
  • 1970-01-01
  • 1970-01-01
  • 2021-05-10
  • 2011-12-09
  • 2012-05-18
  • 2011-10-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多