游戏人生
About Me
  • 你好
  • Math
    • Number
      • Float IEEE754对确定性的影响
      • Pairing Function及其用途
    • Vector and Matrix
      • TRS基础概念
      • LossyScale深入分析
    • Quatenion
      • FromToRotation实现细节
    • Lerp and Curve
      • Slerp球形插值
      • Bezier Curve为什么重要
      • Interpolation和Extrapolation实现细节
  • Programming
    • C#
      • 学习资料
      • C# struct灵魂拷问
      • CIL的世界:call和callvirt
      • .NET装箱拆箱机制
      • .NET垃圾回收机制
    • Go
      • 基础特性
      • 如何正确的判空interface
      • 如何用interface模拟多态
      • 如何定制json序列化
      • 如何安全在循环中删除元素
      • 如何安全关闭channel
      • 如何集成c++库(cgo+swig)
      • 如何性能测试(benchmark, pprof)
    • Lua
      • 基础特性
  • General Game Development
    • Game Engine
      • 学习资料
      • 关于游戏引擎的认知
    • Networking
      • 帧同步
      • 状态同步
      • 物理同步
    • Physics
      • PhysX基本概念
      • PhysX增加Scale支持
      • PhysX场景查询
      • PhysX碰撞检测
      • PhysX刚体动力学
      • PhysX角色控制器
      • PhysX接入项目工程
      • 物理同步
      • 物理破坏
    • Design Pattern
      • 常用设计模式
      • MVP 架构模式
      • ECS 架构模式
  • Unity
    • Runtime
      • Unity拥抱CoreCLR
      • 浅析Mono内存管理
    • UGUI
      • 浅析UGUI渲染机制
      • 浅析UGUI文本优化
      • 介绍若干UGUI实用技巧
    • Resource Management
      • 浅析Unity堆内存的分类和管理方式
      • 深入Unity资源
      • 深入Unity序列化
      • 深入Assetbundle机制
    • Async
      • 深入Unity协程
      • 介绍若干Unity协程实用技巧
      • 异步动作队列
    • Hot Reload
      • Unity+Xlua
      • Xlua Examples学习(一)
      • Xlua Examples学习(二)
    • Editor Extension
    • Performance
      • 浅析Unity Profiler
      • 介绍一个Overdraw分析工具
  • Platform
    • WebGL
  • Real-world Project
    • Souce Engine
    • DOOM3 BFG
Powered by GitBook
On this page
  1. Programming
  2. Go

如何用interface模拟多态

interface中保存着对象的类型和指向值的指针。但要注意,在创建interface对象时,指向对象的类型需要精确指定,而不能依靠自动识别。

首先明确目标:拿到一个*Base对象,调用Foo()方法,但其实调用的是“子类”的Foo方法,这就是多态。

为此需要:

  • Base类中需要利用接口对象保存“子类”的指针,该指针在创建“子类”对象时必须传入。

  • 在需要实现多态的方法中,必须指明调用指针对象的同名方法。

以上缺一不可。另外在函数调用链中,一旦中途子类对象的指针被赋值给了*Base,类型信息就丢失了。

例子

    package main
    import "fmt"
    
    func main() {
      var b *Base = new(Child).Create().GetBase()
      b.Foo() // Sub.Foo is called
    }
    
    type IMatch interface {
      Create() IMatch
      GetBase() *Base
      Foo()
    }
    type Base struct {
      internal IMatch
    }
    type Child struct {
        Base
      }
    // abstract
    func (this *Base) Create() IMatch {
        panic("Base.Create() should not be called")
        return this
    }
    func (this *Base) GetBase() *Base {
          return this
    }
    func (this *Base) Foo() {
      if this.internal != nil {
        this.internal.Foo()
      }
    }
    func (this *Child) Create() IMatch {
        this.internal = this
        return this
    }
    func (this *Child) Foo() {
      fmt.Println("Child.Foo is called")
    }
Previous如何正确的判空interfaceNext如何定制json序列化

Last updated 20 days ago