英文:
Is it possible to have Optional methods inside the interface in golang?
问题
我想为接口创建可选的perim方法。这可能吗?比如说,我不想为三角形创建perim方法,但是它给我报错说缺少一个方法。接口中是否可以有可选的方法?
请告诉我它的替代方法或一些解决方案。
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("矩形的面积:", g.area())
fmt.Println("矩形的周长:", g.perim())
case circle:
fmt.Printf("圆的面积: %.2f\n", g.area())
fmt.Printf("圆的周长: %.2f\n", g.perim())
case square:
fmt.Printf("正方形的面积: %.2f\n", g.area())
fmt.Printf("正方形的周长: %.2f\n", g.perim())
case triangle:
fmt.Printf("三角形的面积: %.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)
}
英文:
I want to create optional perim mehtod for interface. Is it possible?Like I don't want to create perim method for triangle but its giving me error that one method is missing. Is it possible to have optional method in interface?
Please tell me its alternative or some solution.
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)
}
答案1
得分: 3
规范不允许在接口类型中将方法标记为可选的。
请注意,你的实现可以提供其他方法,而不仅仅是接口中定义的方法。可以使用类型断言来检查值的具体类型是否具有“额外”方法,方法是检查它们是否实现了具有这些额外方法的接口类型。
在这个例子中,FooImpl
只有方法 One()
,而 Foo2Impl
有方法 One()
和 Two()
:
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))
}
它的输出结果是:
main.FooImpl(1) doesn't have method Two()
main.Foo2Impl(2) has method Two()
当然,你可以创建一个具有这些额外方法的接口类型:
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 上尝试一下。
英文:
The spec does not allow "marking" methods optional in interface types.
Note that your implementations may provide other methods, not just the methods that are part of the interface you want to implement. Type assertion may be used to check if the concrete type of a value has "additional" methods, by checking if they implement an interface type having those additional methods.
In this example FooImpl
has only method One()
, but Foo2Impl
has methods One()
and Two()
:
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))
}
Its output (try it on the Go Playground):
main.FooImpl(1) doesn't have method Two()
main.Foo2Impl(2) has method Two()
You can of course create an interface type with those additional methods:
type Bar interface {
Two()
}
And then checking it:
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)
}
Try this one on the Go Playground.
答案2
得分: 1
由于您已经在使用type-switch语句,您的参数g
也可以是一个空接口:
func measure(g interface{}) {
fmt.Println(g)
switch v := g.(type) {
case rect:
fmt.Println("矩形面积:", v.area())
fmt.Println("矩形周长:", v.perim())
case circle:
fmt.Printf("圆的面积:%.2f\n", v.area())
fmt.Printf("圆的周长:%.2f\n", v.perim())
case square:
fmt.Printf("正方形的面积:%.2f\n", v.area())
fmt.Printf("正方形的周长:%.2f\n", v.perim())
case triangle:
fmt.Printf("三角形的面积:%.2f\n", v.area())
}
}
这是否是适当的设计(面向对象编程的人可能会不同意),取决于上下文。
英文:
Since you're already using type-switch statements, your argument g
can be an empty interface as well:
func measure(g interface{}) {
fmt.Println(g)
switch v := g.(type) {
case rect:
fmt.Println("Rectangles area :", v.area())
fmt.Println("Rectangle perimeter: ", v.perim())
case circle:
fmt.Printf("Circles Area: %.2f\n", v.area())
fmt.Printf("Circles Perimeter: %.2f\n", v.perim())
case square:
fmt.Printf("Area of square: %.2f\n", v.area())
fmt.Printf("Perimeters of area: %.2f\n", v.perim())
case triangle:
fmt.Printf("Area of triangle: %.2f\n", v.area())
}
}
Whether it's appropriate design (OOP people would disagree), depends on the context.
答案3
得分: -1
接口在定义上不能有可选方法;可选方法无法正常工作。如果你有一个接口类型的值,你可以在该值上调用该接口定义的任何方法。如果一个方法是可选的,你不能假设它是可用的,所以你不能调用它,所以在接口中包含它没有任何意义。
然而,你可以使用多个接口。例如,在net/http
包中就使用了这种方式,其中ResponseWriter
可能是一个Pusher
,在这种情况下,Pusher
描述了“可选”的Push
方法,可以通过类型断言来访问,如下所示:
if ok, pusher := resp.(Pusher); ok {
pusher.Push(...)
}
英文:
Interfaces cannot have optional methods by definition; there's no way for an optional method to work. If you have a value of an interface type, you can call any method defined on that interface on that value. If a method were optional, you couldn't assume it was available, so you couldn't call it, so there would be no point having it in the interface.
You can, however, just use multiple interfaces. This is used in the net/http
package, for example, where a ResponseWriter
may or may not be a Pusher
; in this case, Pusher
describes the "optional" Push
method, which can be accessed by type assertion like so:
if ok,pusher := resp.(Pusher); ok {
pusher.Push(...)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论