亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

在這種特定情況下,在 Go 中模仿繼承的最慣用的方法是什么?

在這種特定情況下,在 Go 中模仿繼承的最慣用的方法是什么?

Go
拉莫斯之舞 2023-05-15 10:03:06
我一直在想很多關于我遇到的這個特殊問題,我應該如何以最干凈的方式解決它。想象一個看起來像這樣的應用程序: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(),但它無法訪問 c.color,因為無法確保實現 AreaCalculator 的結構具有該屬性。我能想到的一種解決方案是這樣做: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())    }}
查看完整描述

2 回答

?
茅侃侃

TA貢獻1842條經驗 獲得超21個贊

一個重要的起點是你不應該模仿 Go 中的繼承。Go 沒有繼承。它有接口,也有嵌入。他們沒有忘記包括繼承;它故意不是語言的一部分。Go 鼓勵組合。

您的Canvas需求不止一個AreaCalculator。它需要提供顏色的東西。你需要表達出來。例如,您可以這樣做:

type DrawableShape interface {

? AreaCalculator

? Color() string

}

然后你會實現Color()forRectangle和Circle。


func (r Rectangle) Color() string {

? return r.color

}


func (c Circle) Color() string {

? return c.color

}

并且children會是[]DrawableShape:


children []DrawableShape

那會留下這樣的東西(建立在 Mohammad 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())

}


查看完整回答
反對 回復 2023-05-15
?
汪汪一只貓

TA貢獻1898條經驗 獲得超8個贊

這里的關鍵觀察是,如果您需要特定功能,請明確說明。也不要代表他們做其他對象的工作。


另請注意,String()必須返回一個字符串,而不是寫入stdout.


package main


import (

    "fmt"

    "math"

    "strings"

)


type AreaCalculator interface {

    fmt.Stringer

    Area() int

}


type Rectangle struct {

    color  string

    width  int

    height int

}


func (r *Rectangle) Area() int {

    return r.width * r.height

}


func (r *Rectangle) String() string {

    return fmt.Sprintf("I'm a rectangle %d", r.width)

}


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) String() string {

    return fmt.Sprintf("I'm a circle: %d", c.diameter)

}


type Canvas struct {

    children []AreaCalculator

}


func (c *Canvas) String() string {

    lines := make([]string, 0)

    for _, child := range c.children {

        lines = append(lines, child.String())

    }

    return strings.Join(lines, "\n")

}


func main() {

    circle := &Circle{color: "red", diameter: 2}

    rect := &Rectangle{color: "blue", width: 3, height: 4}


    canvas := &Canvas{

        children: []AreaCalculator{circle, rect},

    }


    fmt.Println(canvas.String())

}


查看完整回答
反對 回復 2023-05-15
  • 2 回答
  • 0 關注
  • 111 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號