在这种特定情况下,模仿Go中继承的最惯用方式是什么?

marhaupe:

我一直在思考这个特定的问题,我有一种应该以最干净的方式解决它的方法。

想象一个看起来像这样的应用程序:

type AreaCalculator interface {
  Area() int
}

type Rectangle struct {
    color  string
    width  int
    height int
}

type (r *Rectangle) Area() int {
   return r.width * r.height
}

type Circle struct {
    color    string
    diameter int
}

type (c *Circle) Area() int {
   return r.diameter / 2 * r.diameter / 2 * π
}

type Canvas struct {
    children []AreaCalculator
}

func (c *Canvas) String() {
    for child := range c.children {
        fmt.Println("Area of child with color ", child.color, " ", child.Area())
    }
}

该示例显然无法编译,因为尽管Canvas的String()方法可以调用c.Area(),但由于无法确保实现AreaCalculator的结构具有该属性,因此它无法访问c.color。

我能想到的一种解决方案是这样做:

type AreaCalculator interface {
  Area() int
  Color() string
}

type Rectangle struct {
    color  string
    width  int
    height int
}

type (r *Rectangle) Color() string {
   return r.color
}

type (r *Rectangle) Area() int {
   return r.width * r.height
}

type Circle struct {
    color    string
    diameter int
}

type (c *Circle) Area() int {
   return r.diameter / 2 * r.diameter / 2 * π
}
type (c *Circle) Color() string {
   return c.color
}

type Canvas struct {
    children []AreaCalculator
}

func (c *Canvas) String() {
    for child := range c.children {
        fmt.Println("Area of child with color ", child.Color(), " ", child.Area())
    }
}

另一种方法是尝试这样的事情:

type Shape struct {
    Area func() int 
    color string
    diameter int
    width int
    height int
}

func NewCircle() Shape {
    // Shape initialisation to represent a Circle. Setting Area func here
}


func NewRectangle() Shape {
    // Shape initialisation to represent a Rectangle. Setting Area func here
}

type Canvas struct {
    children []Shape
}

func (c *Canvas) String() {
    for child := range c.children {
        fmt.Println("Area of child with color", child.color, " ", child.Area())
    }
}

这些选项对我来说似乎都不干净。我敢肯定,有一种我无法想到的更清洁的解决方案。

罗布·纳皮尔(Rob Napier):

重要的出发点是您不应模仿Go中的继承。Go没有继承。它具有接口并且具有嵌入。他们没有忘记包括继承。它不是语言的一部分Go鼓励作文。

您的Canvas需求不只是一个AreaCalculator它需要提供颜色的东西。您需要表达这一点。例如,您可以这样做:

type DrawableShape interface {
  AreaCalculator
  Color() string
}

然后你会实现Color()RectangleCircle

func (r Rectangle) Color() string {
  return r.color
}

func (c Circle) Color() string {
  return c.color
}

并且children将是[]DrawableShape

children []DrawableShape

这将使像这样(建筑穆罕默德Nasirifar的代码关闭)。

package main

import (
    "fmt"
    "math"
    "strings"
)

type AreaCalculator interface {
    Area() int
}

type DrawableShape interface {
  AreaCalculator
  Color() string
}

type Rectangle struct {
    color  string
    width  int
    height int
}

func (r Rectangle) Area() int {
    return r.width * r.height
}

func (r Rectangle) Color() string {
  return r.color
}

type Circle struct {
    color    string
    diameter int
}

func (c Circle) Area() int {
    area := math.Round(float64(c.diameter*c.diameter) * math.Pi / float64(4))
    return int(area)
}

func (c Circle) Color() string {
  return c.color
}

type Canvas struct {
    children []DrawableShape
}

func (c Canvas) String() string {
    lines := make([]string, 0)
    for _, child := range c.children {
        lines = append(lines, fmt.Sprintf("Area of child with color %s %d", child.Color(), child.Area()))
    }
    return strings.Join(lines, "\n")
}

func main() {
    circle := &Circle{color: "red", diameter: 2}
    rect := &Rectangle{color: "blue", width: 3, height: 4}

    canvas := &Canvas{
        children: []DrawableShape{circle, rect},
    }

    fmt.Println(canvas.String())
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

在这种特定情况下 {xor} 的确切含义是什么?

在这种特定情况下,为什么在堆栈上分配大元素不会失败?

在这种情况下,Go 在语法上的问题是什么?

> =在这种情况下是什么意思

在这种情况下 res 是什么意思?

在这种情况下,语法[]是什么意思?

在这种情况下,`typedef`是什么意思

在这种情况下,svn更新的流程是什么?

在这种情况下,括号是什么意思?

在这种情况下,运算符“(> =)”是什么?

C ++:在这种情况下引用的优点是什么?

jQuery:在这种情况下,.on()的正确用法是什么?

在这种情况下,熵是什么意思?

在这种情况下setViewControllers的目的是什么

在这种特定情况下,如何使用 javascript 删除 HTML 元素

后缀运算符在这种特定情况下(JAVA)如何工作?

在这种特定情况下,如何使用流获取列表列表?

jQuery:在这种特定情况下,如何恢复点击事件的初始状态?

在这种特定情况下,目录权限和文件权限之间的差异

在这种特定情况下,如何阻止Eclipse缩进多余的空格?

在这种特定情况下,更快的IO会导致结果变慢

在 python 中, input() 函数在这种特定情况下对我不起作用

在这种特定情况下,如何设计类以共享其方法声明?

在这种特定情况下,使用apt-get autoremove命令安全吗?

在这种特定情况下,如何修复损坏的包装?

在这种特定情况下,有没有更有效的方式来编写我的过滤器?

在这种情况下,什么是“生成”?

在这种特定情况下,我们可以使用android数据绑定替换findViewById()吗?

令牌是什么!在这种情况下(与绑定一起)是什么意思?