go - golang 接口(interface)中是否可以有可选方法?

标签 go methods interface

我想为界面创建可选的 perim 方法。有可能吗?就像我不想为三角形创建 perim 方法,但它给了我缺少一种方法的错误。接口(interface)中是否可以有可选方法?

请告诉我它的替代方案或某种解决方案。

type geometry interface {
    area() float64
    perim() float64
}

type rect struct {
    width, height float64
}

type triangle struct {
    base, height float64
}

type circle struct {
    radius float64
}

type square struct {
    side float64
}

func (r rect) area() float64 {
    return r.width * r.height
}

func (r rect) perim() float64 {
    return 2*r.width + 2*r.height
}

func (c circle) area() float64 {
    return math.Pi * c.radius * c.radius
}

func (c circle) perim() float64 {
    return 2 * math.Pi * c.radius
}

func (t triangle) area() float64 {
    return 1 / 2 * t.base * t.height
}

func measure(g geometry) {
    fmt.Println(g)
    switch g.(type) {
    case rect:
        fmt.Println("Rectangles area :", g.area())
        fmt.Println("Rectangle perimeter: ", g.perim())
    case circle:
        fmt.Printf("Circles Area: %.2f\n", g.area())
        fmt.Printf("Circles Perimeter: %.2f\n", g.perim())
    case square:
        fmt.Printf("Area of square: %.2f\n", g.area())
        fmt.Printf("Perimeters of area: %.2f\n", g.perim())
    case triangle:
        fmt.Printf("Area of  triangle: %.2f\n", g.area())
    }
}

func main() {
    r := rect{width: 3, height: 4}
    c := circle{radius: 5}
    s := square{side: 7}
    t := triangle{base: 3, height: 4}
    measure(r)
    measure(c)
    measure(s)
    measure(t)
}

最佳答案

规范不允许 interface 中可选的“标记”方法类型。

请注意,您的实现可能会提供其他方法,而不仅仅是您要实现的接口(interface)的一部分的方法。 Type assertion可用于通过检查值的具体类型是否实现具有这些附加方法的接口(interface)类型来检查它们是否具有“附加”方法。

在此示例中,FooImpl 仅具有方法 One(),但 Foo2Impl 具有方法 One() 并且两个():

type Foo interface {
    One()
}

type FooImpl int

func (fi FooImpl) One() {}

type Foo2Impl int

func (fi Foo2Impl) One() {}
func (fi Foo2Impl) Two() {}

func check(f Foo) {
    if ft, ok := f.(interface{ Two() }); ok {
        fmt.Printf("%T(%v) has method Two()\n", f, f)
        ft.Two() // You can call it
    } else {
        fmt.Printf("%T(%v) doesn't have method Two()\n", f, f)
    }
}

func main() {
    check(FooImpl(1))
    check(Foo2Impl(2))
}

它的输出(在 Go Playground 上尝试一下):

main.FooImpl(1) doesn't have method Two()
main.Foo2Impl(2) has method Two()

您当然可以使用这些附加方法创建接口(interface)类型:

type Bar interface {
    Two()
}

然后检查它:

if ft, ok := f.(Bar); ok {
    fmt.Printf("%T(%v) has method Two()\n", f, f)
    ft.Two() // You can call it
} else {
    fmt.Printf("%T(%v) doesn't have method Two()\n", f, f)
}

Go Playground 上试试这个.

关于go - golang 接口(interface)中是否可以有可选方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67823459/

相关文章:

mysql - 如何在 Go-Gorm 中禁用默认错误记录器

go - 库网络 : Error: unknown command "/var/run/docker/netns/582bd184e561" for "some_app"

go - 在 golang 中实现 github.com/jlaffaye/ftp

java - 定义一个与其所在类同名的枚举

java - 确定按下按钮时是否选中复选框

java - 如何在 java 中设置芬兰语言环境?

mysql安全读-更新-写

表达式计算的 C++ 设计问题

c# - 还有哪些其他语言支持 Go 的接口(interface)风格而无需显式声明?

cocoa - 如何将WebView插入到cocoa应用程序中?