duandazhen7306 2016-10-22 18:36
浏览 38
已采纳

进行“多态”

People are saying, Go is not an OO (Object Oriented) language; don't use OO terms on Go. OK, let me describe what I am able to do with OO --

With an OO language, I can make different animals say different things based on their classes:

cat.Say() // miao
sheep.Say() // bahh
cow.Say() // moo

The same is getting the Area() from Shapes.

However, this go demo code made me believe that it is impossible. Included below as Exhibit#1.

Then today, I found this go demo code, which makes it entirely possible. Included below as Exhibit#2.

So my question is, what's fundamentally different between the two, that makes the first one wrong and second one correct? How to make the first one "works"?

Exhibit#1:

// Credits: hutch
//          https://groups.google.com/d/msg/golang-nuts/N4MBApd09M8/0ij9yGHK_8EJ
////////////////////////////////////////////////////////////////////////////

/*

https://groups.google.com/d/msg/golang-nuts/N4MBApd09M8/tOO5ZXtwbhYJ

LRN:

Subtype polymorphism: Not applicable (Go doesn't have subtyping).
Although if you embed a struct A implementing interface X into a struct B,
struct B will implement interface X, and can be used instead of struct A in
places where struct A is expected. So, kind of yes.

Robert Johnstone:

interfaces behave similarly to virtual functions, but they are not identical.  See the (following) example program by hutch.

*/

package main

import "fmt"

type A struct {
    astring string
}

type B struct {
    A
    bstring string
}

type Funny interface {
    strange()
    str() string
}

func (this *A) strange() {
    fmt.Printf("my string is %q
", this.str())
}

func (this *A) str() string {
    return this.astring
}

func (this *B) str() string {
    return this.bstring
}

func main() {
    b := new(B)
    b.A.astring = "this is an A string"
    b.bstring = "this is a B string"

    b.strange()
    // Output: my string is "this is an A string"

    // Many people familiar with OO (and unfamiliar with Go) will be quite
    // surprised at the output of that program.
}

Exhibit#2:

// Credits: https://play.golang.org/p/Zn7TjiFQik
////////////////////////////////////////////////////////////////////////////

/*

Problem (From Polymorphism-Subtype.go):

https://groups.google.com/d/msg/golang-nuts/N4MBApd09M8/tOO5ZXtwbhYJ

LRN: Subtype polymorphism: Not applicable (Go doesn't have subtyping).

Goal:

This is to demo that "polymorphism" is still doable in Go.

*/

package main

import (
    "fmt"
)

type Shape interface {
    Area() float32
}

type Point struct {
    x float32
    y float32
}

// Make sure the structs are different sizes so we're sure it'll work with
// all sorts of types
type Circle struct {
    center Point
    radius float32
}

func (c Circle) Area() float32 {
    return 3.1415 * c.radius * c.radius
}

type Rectangle struct {
    ul Point
    lr Point
}

func (r Rectangle) Area() float32 {
    xDiff := r.lr.x - r.ul.x
    yDiff := r.ul.y - r.lr.y
    return xDiff * yDiff
}

func main() {
    mtDict := make(map[string]Shape)
    // No problem storing different custom types in the multitype dict
    mtDict["circ"] = Circle{Point{3.0, 3.0}, 2.0}
    mtDict["rect"] = Rectangle{Point{2.0, 4.0}, Point{4.0, 2.0}}

    for k, v := range mtDict {
        fmt.Printf("[%v] [%0.2f]
", k, v.Area())
    }
}

/*

$ go run Polymorphism-Shape.go
[circ] [12.57]
[rect] [4.00]

*/
  • 写回答

2条回答 默认 最新

  • dongwo5589 2016-10-22 19:19
    关注

    Your two exhibits are doing different things.

    In the first one, B has A embedded in it, and B doesn't implement the strange() method itself, so when you call b.strange(), you get the implementation of strange() defined for A. The receiver (this) of the strange method is b.A, not b, so the value b.A.astring is printed. If you wanted strange to print bstring, you would have to define strange for B.

    This points out one of the differences between Go and other OO languages: embedding A within B does not mean that B is a "subclass" of A, so an object of type B cannot be used where an object of type A is expected. However, since B inherits the fields and methods of A, any interface that's implemented by A is also implemented by B, and, unless those methods are defined specifically for B, they operate on the A within B, not B itself.

    In the second exhibit, you have the Shape interface which is implemented by the types Circle and Rectangle. The element type of your map is Shape, so any type that implements that interface can be an element in the map. When working with a value of an interface type as you are doing in the loop, you can call any method defined in the interface on the value, and the definition corresponding to the actual type of the value will be called.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 高价求中通快递查询接口
  • ¥15 解决一个加好友限制问题 或者有好的方案
  • ¥15 关于#java#的问题,请各位专家解答!
  • ¥15 急matlab编程仿真二阶震荡系统
  • ¥20 TEC-9的数据通路实验
  • ¥15 ue5 .3之前好好的现在只要是激活关卡就会崩溃
  • ¥50 MATLAB实现圆柱体容器内球形颗粒堆积
  • ¥15 python如何将动态的多个子列表,拼接后进行集合的交集
  • ¥20 vitis-ai量化基于pytorch框架下的yolov5模型
  • ¥15 如何实现H5在QQ平台上的二次分享卡片效果?