Go中struct组合与Java继承的区别

参考解析

题目来源:快手

答案:

两者都是在编译期实现的。
Go语言的继承通过匿名组合完成:基类以Struct的方式定义,子类只需要把基类作为成员放在子类的定义中,支持多继承。
Java的继承通过extends关键字完成,不支持多继承。

示例Go代码:

  1. package main
  2. import "fmt"
  3. type People struct{}
  4. func (p *People) ShowA() {
  5. fmt.Println("people showA")
  6. p.ShowB()
  7. }
  8. func (p *People) ShowB() {
  9. fmt.Println("people showB")
  10. }
  11. type Teacher struct {
  12. People
  13. }
  14. func (t *Teacher) ShowB() {
  15. fmt.Println("teacher showB")
  16. }
  17. func main() {
  18. t := Teacher{}
  19. t.ShowA()
  20. }
  21. //输出结果:
  22. //people showA
  23. //people showB

示例java代码

  1. public class People {
  2. public void showA() {
  3. System.out.println("ShowA");
  4. this.showB();
  5. }
  6. public void showB() {
  7. System.out.println("ShowB");
  8. }
  9. }
  10. public class Teacher extends People{
  11. public void showB() {
  12. System.out.println("ShowTeacherB");
  13. }
  14. public static void main(String[] args){
  15. Teacher t = new Teacher();
  16. t.showA();
  17. }
  18. }
  19. //ShowA
  20. //ShowTeacherB

在编译期,Go的编译器会自动给Teacher生成一个ShowA函数,内部调用一个People实例的showA函数,这样调用顺序是Teacher.ShowA()->People.ShowA()->People.ShowB()。Go的继承在运行时仍然是一个组合关系,Teacher仍然要通过People的实例去调用People的函数。

  1. func (t *Teacher) ShowA() {
  2. t.People.ShowA()
  3. }

Java的编译器则会把People ShowA函数的内容拷贝过来给Teacher生成一个ShowA函数,里面的this在运行时对应的就是Teacher的实例,所以调用顺序是Teacher.showA()->Teacher.showB()。Java在运行时Teacher实例内部不会再有People的实例存在。

  1. public void showA() {
  2. System.out.println("ShowA");
  3. this.showB();
  4. }

通过以上两段代码发现,go调用ShowB()方法时并没有去子类调用,而是使用父类的ShowB()方法
Go并不支持完全的面向对象,但这并不代表Go不支持面向对象,只是有些地方在使用的时候需要去注意,避免踩坑。