秒懂 go 语言的继承

对于go语言的继承,之前总是模模糊糊的分不清是什么。不知道如何通过何种方式来继承的。

秒懂 go 语言的继承

然后我就开始对照着java的方式,用java实现继承,然后用go语言实现同样的继承。

java的继承

// 动物类
class Animal {
    public   String name;
    public String subject;

    void eat(String food) {
        System.out.println(name + "喜欢吃:" + food + ",它属于:" + subject);
    }
}

// 猫类。 猫类继承动物类
class Cat extends Animal{
    // 猫自己的属性和方法
    public int age;
    void sleep() {
        System.out.println(name + "今年" + age + "岁了,特别喜欢睡觉");
    }
}

public class Test{
    public static void main(String[] args){
        // 创建一个动物实例
        Animal a = new Animal();
        a.name = "动物";
        a.subject = "动物科";
        a.eat("肉");

        // 创建一个猫实例
        Cat cat = new Cat();
        cat.name = "咪咪";
        cat.subject = "猫科";
        cat.age = 1;
        cat.eat("鱼");
        cat.sleep();
    }
}
输出结果入下:
    动物喜欢吃:肉,它属于:动物科
    咪咪喜欢吃:鱼,它属于:猫科
    咪咪今年1岁了,特别喜欢睡觉

go 语言实现继承

package main

import (
  "fmt"
  "strconv"
)

// 动物类
type Animal struct {
  name string
  subject string
}

// 动物的公共方法
func (a *Animal) eat(food string) {
  fmt.Println(a.name + "喜欢吃:" + food +",它属于:" + a.subject)
}

// 猫类,继承动物类
type Cat struct {
  // 继承动物的属性和方法
  Animal
  // 猫自己的属性
  age int
}

// 猫类独有的方法
func (c Cat) sleep() {
  fmt.Println(c.name + " 今年" + strconv.Itoa(c.age) + "岁了,特别喜欢睡觉")
}

func main() {
  // 创建一个动物类
  animal := Animal{name:"动物", subject:"动物科"}
  animal.eat("肉")

  // 创建一个猫类
  cat := Cat{Animal: Animal{name:"咪咪", subject:"猫科"},age:1}
  cat.eat("鱼")
  cat.sleep()
}
输出结果:
    动物喜欢吃:肉,它属于:动物科
    咪咪喜欢吃:鱼,它属于:猫科
    咪咪 今年1岁了,特别喜欢睡觉

是不是有点懂了,但是这只是最基础的封装,现在,在其他语言中,我们都知道,大多数都是以 interface 的方式来进行封装的。那么我们用 interface ,以一种高级的方式改造上面的例子如下:

使用接口的方式进行封装一个方法

package main

import (
"fmt"
"strconv"
)

type Animaler interface {
    eat()
}

type Animal struct {
    name string
    age int
    food string
}

// 实现 eat() 方法
func (animal Animal) eat() {
    fmt.Println(animal.name + "今年"+ strconv.Itoa(animal.age) +"岁了," + "喜欢吃" + animal.food)
}

type Cat struct {
    Animal
    time int
}

type Dog struct {
    Animal
    plays string
}

// 猫独有的方法
func (cat Cat) sleep() {
    fmt.Println("我叫" + cat.name + ", 我能睡" + strconv.Itoa(cat.time) + "分钟" )
}
// 狗独有的方法
func (dog Dog) play() {
    fmt.Println("我叫" + dog.name + "我喜欢玩" + dog.plays)
}

func testInterface(animaler Animaler)  {
    animaler.eat()
}

func main()  {
    cat := Cat{Animal:Animal{name:"咪咪", age:2, food:"鱼"}, time: 8}
    cat.sleep()
    testInterface(cat)

    dog := Dog{Animal:Animal{name:"大黄", age:2, food:"骨头"}, plays:"球球"}
    dog.play()
    testInterface(dog)
}

输出结果:

我叫咪咪, 我能睡8分钟
咪咪今年2岁了,喜欢吃鱼
我叫大黄我喜欢玩球球
大黄今年2岁了,喜欢吃骨头

总结

通过如上的代码可以看到,

  • 在go语言中, type name struct{} 结构体 就相当于其他语言中的 class 类的概念。
  • 在其他语言中,方法是直接写在在 类 里面的,而在go语言中,我们对于该结构体,如果存在方法,比如猫咪存在睡觉的方法那么是以 func (结构体名) 方法名{},即func(c Cat) sleep{} 的方式来声明方法。
  • 在java中, string + int = string,int类型的值不需要类型转换,而在go语言中,string + int,如果想要一个字符串,则需要对int 类型的值转换为string类型,然后才能拼接。

下面着这两句话一定要熟记:

  • 结构体解决的是基本数据类型不能满足我们日常需要的问题。再简单点理解就是一个结构体就是一个 json 类型的 object。
  • 接口是一种类型。是一种特殊的类型,它规定了不同结构体有哪些相同的行为,只是制定标准,而不实现标准。就好比自来水厂只规定水龙头的半径大小,而不去考虑谁生产水龙头,生产水龙头的厂家不管用什么材料,只需要按照自来水厂的标准制定就好。

如果有不对的,希望各位大佬批评指正。感激不尽。

这是我本人的片面理解,仅仅是为了学习起来更快和更容易理解,而go语言本身是不推荐继承这个概念的,详细的可以参考这篇文章:studygolang.com/articles/17257

秒懂 go 语言的继承

秒懂 go 语言的继承

go
本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 16

@lovecn 没有啊,我这边正常显示 :flushed:

4年前 评论

@shadowfpj 不胜荣幸 :grinning:

4年前 评论
Summer

图片挂了,你是因为本地有缓存,去除缓存就可以看到无法访问了,或者换一个浏览器:

file

4年前 评论

@Summer 好的,我重新修改下

4年前 评论

Go语言继承说白了就是结构体内嵌

4年前 评论

@Shenhi 是的,子类的结构体中将父类结构体的名字添加进去,就相当于实现了继承

4年前 评论
yourself

go设计的思想就是用组合代替继承,这是个人的理解

4年前 评论

@yourself 也没错,我没有试go里面是不是可以多继承。

4年前 评论
yourself

@pureyb 推荐你看一下这篇文章希望对你有启发,我个人不建议用继承来理解go,容易让你掉入传统语言的思想里(不是说你理解的完全不对)。
https://studygolang.com/articles/17257

4年前 评论

@yourself 感谢指正,因为或多或少学习的时候就想和其他语言做比较。所以就类似对比一下,看了你推荐的链接,获益匪浅。再次表示感谢 :+1: :+1: :+1:

4年前 评论
yourself

@pureyb 推荐你可以去学习雨痕大佬的go语言学习笔记。

4年前 评论

Golang多态的写法了解下哈哈哈,我也才学。多多交流。

package main

import "fmt"

type Animaler interface {
    Eat()
}

type Animal struct {
    name string
}

type Cat struct {
    animal Animal
    age    int
}

func (cat Cat) Eat() {
    fmt.Println("猫吃鱼","我今年:",cat.age,"岁")
}

type Dog struct {
    animal Animal
    age    int
}

func (dog Dog) Eat() {
    fmt.Println("狗吃肉","我今年:",dog.age,"岁")
}

func main() {

    var animal Animaler = Cat{animal: Animal{name: "喵喵"}, age: 9}

    animal.Eat()

    animal = Dog{animal:Animal{name: "狗狗"}, age:10}

    animal.Eat()
}
4年前 评论

@AaronGo

package main

import (
    "fmt"
    "strconv"
)

type Animaler interface {
    eat()
}

type Animal struct {
    name string
    age int
    food string
}

func (animal Animal) eat() {
    fmt.Println(animal.name + "今年"+ strconv.Itoa(animal.age) +"岁了," + "喜欢吃" + animal.food)
}

type Cat struct {
    Animal
    time int
}

type Dog struct {
    Animal
    plays string
}

func (cat Cat) sleep() {
    fmt.Println("我叫" + cat.name + ", 我能睡" + strconv.Itoa(cat.time) + "分钟" )
}

func (dog Dog) play() {
    fmt.Println("我叫" + dog.name + "我喜欢玩" + dog.plays)
}

func testInterface(animaler Animaler)  {
    animaler.eat()
}

func main()  {
    cat := Cat{Animal:Animal{name:"咪咪", age:2, food:"鱼"}, time: 8}
    cat.sleep()
    testInterface(cat)

    dog := Dog{Animal:Animal{name:"大黄", age:2, food:"骨头"}, plays:"球球"}
    dog.play()
    testInterface(dog)
}
4年前 评论
pureyb (作者) (楼主) 4年前
Neilyozの鱼不浪 4年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!