深入理解D5/Tengo中的对象类型系统

深入理解D5/Tengo中的对象类型系统

tengo A fast script language for Go tengo 项目地址: https://gitcode.com/gh_mirrors/te/tengo

引言

D5/Tengo作为一门动态类型脚本语言,其核心特性之一就是灵活的对象类型系统。本文将全面解析Tengo中的对象类型机制,包括内置运行时类型和用户自定义类型的实现方式,帮助开发者更好地理解和扩展Tengo语言。

对象接口基础

在Tengo中,所有对象类型都必须实现Object接口,这是类型系统的基石。Object接口定义了类型必须实现的一系列方法,这些方法决定了对象在运行时如何表现。

核心方法解析

  1. TypeName() string

    • 返回类型名称字符串
    • 主要用于调试和错误报告
    • 建议保持简短且具有区分度
  2. String() string

    • 返回对象的字符串表示形式
    • 在需要字符串转换时自动调用
    • 影响print等函数的输出
  3. BinaryOp(op token.Token, rhs Object) (Object, error)

    • 实现运算符重载的关键方法
    • 支持+-*等二元运算符
    • 注意:<<=通过交换操作数实现
  4. IsFalsy() bool

    • 定义对象的"假值"概念
    • 影响if、while等条件判断
    • 例如:空数组、空字符串、0、false等应返回true
  5. Equals(Object) bool

    • 定义对象相等性逻辑
    • 建议保持跨类型比较的一致性

高级特性实现

可索引对象

通过实现以下方法,对象可以支持索引访问:

IndexGet(index Object) (value Object, err error)
IndexSet(index, value Object) error

典型应用场景:

  • 数组类型:索引为整数
  • 字典类型:索引为字符串
  • 自定义数据结构:可定义任意索引类型

可调用对象

通过实现以下方法,对象可以像函数一样被调用:

CanCall() bool
Call(args ...Object) (ret Object, err error)

应用场景:

  • 函数对象
  • 可调用类实例
  • 特殊操作符重载

可迭代对象

通过实现以下方法,对象可以用于for-in循环:

CanIterate() bool
Iterate() Iterator

迭代器接口需要实现:

  • Next() bool - 是否还有下一个元素
  • Key() Object - 当前元素的键
  • Value() Object - 当前元素的值

运行时内置类型

Tengo提供了一系列内置类型,开发者可以直接使用:

  1. 基本类型

    • Int - 整数
    • Float - 浮点数
    • String - 字符串
    • Bool - 布尔值
    • Char - 字符
    • Bytes - 字节数组
    • Time - 时间
  2. 复合类型

    • Array - 可变数组
    • ImmutableArray - 不可变数组
    • Map - 可变字典
    • ImmutableMap - 不可变字典
  3. 函数类型

    • CompiledFunction - 编译函数
    • BuiltinFunction - 内置函数
    • UserFunction - 用户函数
  4. 特殊类型

    • Error - 错误对象
    • Undefined - 未定义值
    • Break/Continue/ReturnValue - 流程控制

自定义类型实践

通过实现Object接口,开发者可以轻松扩展Tengo的类型系统。下面是一个完整的自定义字符串数组类型示例:

type StringArray struct {
    tengo.ObjectImpl  // 嵌入默认实现
    Value []string    // 实际数据存储
}

// 必须实现的方法
func (o *StringArray) TypeName() string { return "string-array" }
func (o *StringArray) String() string { return strings.Join(o.Value, ", ") }

// 可选实现的方法
func (o *StringArray) BinaryOp(op token.Token, rhs tengo.Object) (tengo.Object, error) {
    // 实现+运算符连接数组
    if rhs, ok := rhs.(*StringArray); ok && op == token.Add {
        return &StringArray{Value: append(o.Value, rhs.Value...)}, nil
    }
    return nil, tengo.ErrInvalidOperator
}

func (o *StringArray) IsFalsy() bool { return len(o.Value) == 0 }

// 索引访问实现
func (o *StringArray) IndexGet(index tengo.Object) (tengo.Object, error) {
    if idx, ok := index.(*tengo.Int); ok {
        if idx.Value >= 0 && idx.Value < int64(len(o.Value)) {
            return &tengo.String{Value: o.Value[idx.Value]}, nil
        }
        return nil, tengo.ErrIndexOutOfBounds
    }
    return nil, tengo.ErrInvalidIndexType
}

// 函数调用实现
func (o *StringArray) CanCall() bool { return true }
func (o *StringArray) Call(args ...tengo.Object) (tengo.Object, error) {
    if len(args) != 1 {
        return nil, tengo.ErrWrongNumArguments
    }
    // 实现查找字符串返回索引的功能
    if s, ok := tengo.ToString(args[0]); ok {
        for i, v := range o.Value {
            if v == s {
                return &tengo.Int{Value: int64(i)}, nil
            }
        }
        return tengo.UndefinedValue, nil
    }
    return nil, tengo.ErrInvalidArgumentType{...}
}

// 迭代器实现
func (o *StringArray) CanIterate() bool { return true }
func (o *StringArray) Iterate() tengo.Iterator {
    return &StringArrayIterator{strArr: o, idx: -1}
}

type StringArrayIterator struct {
    tengo.ObjectImpl
    strArr *StringArray
    idx    int
}

func (i *StringArrayIterator) Next() bool {
    i.idx++
    return i.idx < len(i.strArr.Value)
}
func (i *StringArrayIterator) Key() tengo.Object {
    return &tengo.Int{Value: int64(i.idx)}
}
func (i *StringArrayIterator) Value() tengo.Object {
    return &tengo.String{Value: i.strArr.Value[i.idx]}
}

最佳实践建议

  1. 类型设计原则

    • 保持类型行为的一致性
    • 合理处理边界情况
    • 提供有意义的错误信息
  2. 性能考虑

    • 避免频繁的对象创建
    • 考虑使用指针接收器
    • 缓存常用对象
  3. 交互性

    • 提供完整的字符串表示
    • 支持常用运算符
    • 考虑与内置类型的互操作性

总结

Tengo的对象类型系统设计精巧而灵活,既提供了丰富的基础类型,又允许开发者通过实现Object接口来扩展语言功能。理解这一机制对于深度使用Tengo或开发Tengo扩展至关重要。通过合理设计自定义类型,可以大大增强Tengo的表达能力和适用场景。

tengo A fast script language for Go tengo 项目地址: https://gitcode.com/gh_mirrors/te/tengo

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

萧崧锟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值