首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Go“多态性”

Go“多态性”
EN

Stack Overflow用户
提问于 2016-10-22 18:36:54
回答 2查看 274关注 0票数 2

人们说,Go不是一种面向对象的语言;不要在Go上使用OO术语。好的,让我来描述一下我能用OO做什么--

使用OO语言,我可以让不同的动物根据他们的类说不同的话:

代码语言:javascript
复制
cat.Say() // miao
sheep.Say() // bahh
cow.Say() // moo

从形状中获取面积()也是如此。

然而,这个go演示代码让我相信这是不可能的。作为Exhibit#1包括在下面。

然后今天,我找到了这个go演示代码,这使它完全成为可能。作为Exhibit#2包括在下面。

所以我的问题是,两者之间有什么根本的区别,使得第一个错误和第二个错误是正确的?如何使第一个“工作”?

Exhibit#1:

代码语言:javascript
复制
// 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\n", 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:

代码语言:javascript
复制
// 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]\n", k, v.Area())
    }
}

/*

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

*/
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-10-22 19:19:37

你的两个展品在做不同的事情。

在第一个例子中,B嵌入了A,而B没有实现strange()方法本身,所以当您调用b.strange()时,您将得到为A定义的strange()的实现。strange方法的接收方(strange)是b.A,而不是b,因此将打印值b.A.astring。如果希望strange打印bstring,则必须为B定义strange

这指出了Go和其他面向对象语言之间的一个区别:将A嵌入到B中并不意味着BA的“子类”,因此在需要A类型的对象时不能使用B类型的对象。但是,由于B继承了A的字段和方法,由A实现的任何接口也都由B实现,并且,除非这些方法是专门为B定义的,否则它们在B中的A上操作,而不是B本身。

在第二个演示中,您有Shape接口,它由CircleRectangle类型实现。映射的元素类型是Shape,因此实现该接口的任何类型都可以是映射中的元素。当像在循环中一样使用接口类型的值时,可以调用该值上接口中定义的任何方法,并且将调用与该值的实际类型相对应的定义。

票数 2
EN

Stack Overflow用户

发布于 2016-10-22 19:09:44

首先,我想谈一谈“不可能”部分。

代码语言:javascript
复制
import "fmt"

type Animal interface {
    Say() string
}

type Cat struct {}

func (cat Cat) Say() string {
    return "miao"
}

type Sheep struct {}

func (sheep Sheep) Say() string {
    return "bahh"
}

type Cow struct {}

func (cow Cow) Say() string {
    return "moo"
}

func main() {

    cat := Cat{}
    sheep := Sheep{}
    cow := Cow{}

    fmt.Println(cat.Say())
    fmt.Println(sheep.Say())
    fmt.Println(cow.Say())
}

这将与你所期望的完全一样。因此,在“不同的结构对同一方法的响应不同”方面存在多态性。

Exhibit#1的意图表明,Go所做的实际上类似于@重载之前的Java铸件。

只需将以下方法添加到第一个示例中,就可以了解该方法的工作原理:

代码语言:javascript
复制
func (this B) strange() {
    fmt.Printf("my string is %q\n", this.str())
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40195682

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档