Skip to content
当前页大纲

Mojo struct 结构体与生命周期

本篇覆盖:struct 定义、@fieldwise_init、生命周期方法(构造/拷贝)、运算符重载。struct 是 Mojo 组织数据的基本方式,也是它与 Python 分道扬镳的第一站。

一、struct:静态版的 class

Mojo 用 struct 组织自定义类型,概念上对应 Python 的 class,但有一个根本区别:struct 完全静态绑定——字段、方法在编译期就确定,没有运行时动态派发,没有猴子补丁。

mojo
@fieldwise_init
struct MyPair(Copyable):
    var first: Int
    var second: Int

    def dump(self):
        print(self.first, self.second)

def main():
    var mine = MyPair(2, 4)
    mine.dump()       # 2 4

三个要点:

  1. 字段用 var 声明(和局部变量一样)
  2. 括号里的 Copyable 是 trait(下一篇细讲)——声明这个类型支持拷贝
  3. @fieldwise_init 自动生成字段级构造函数,不用手写 __init__

二、手写生命周期方法

当初始化逻辑比「逐字段赋值」复杂时,需要手写生命周期方法:

mojo
struct MyPair(Copyable):
    var first: Int
    var second: Int

    # 构造函数:注意 out self 约定
    def __init__(out self, first: Int, second: Int):
        self.first = first
        self.second = second

    # 拷贝构造:从已有实例创建新实例
    def __init__(out self, *, copy: Self):
        self.first = copy.first
        self.second = copy.second

    def dump(self):
        print(self.first, self.second)

注意 out self:构造函数开始时 self 尚未初始化,函数必须完成初始化后才能返回。这是 Mojo 内存安全的基石之一——不可能拿到「半初始化」的对象。

日常开发中,绝大多数 struct 用 @fieldwise_init + trait 自动合成就够了:

mojo
@fieldwise_init
struct Vec3(Movable, Copyable):
    var x: Float64
    var y: Float64
    var z: Float64

三、运算符重载:dunder 方法

和 Python 一致的 dunder 风格:

mojo
@fieldwise_init
struct Vec2(Copyable, Stringable):
    var x: Float64
    var y: Float64

    def __add__(self, rhs: Vec2) -> Vec2:
        return Vec2(self.x + rhs.x, self.y + rhs.y)

    def __mul__(self, k: Float64) -> Vec2:
        return Vec2(self.x * k, self.y * k)

    def __str__(self) -> String:
        return t"({self.x}, {self.y})"

def main():
    var a = Vec2(1.0, 2.0)
    var b = Vec2(3.0, 4.0)
    print(a + b)        # (4.0, 6.0)
    print(a * 2.0)      # (2.0, 4.0)

Stringable trait 要求实现 __str__——实现后 print() 直接可用。这是 trait 系统的第一次亮相:能力靠声明 trait + 实现 dunder 获得,而不是继承。

四、struct vs Python class 对比

特性Python classMojo struct
方法绑定运行时动态编译期静态
字段增删运行时可变编译期锁定
继承支持多继承用 trait 组合替代
构造__init__(self)__init__(out self) + @fieldwise_init
性能有解释器开销零成本抽象

官方路线图提到未来会支持 Python 风格的动态 class,用于上层胶水代码——Mojo 的思路是静态 struct 管性能路径,未来动态 class 管灵活场景

五、嵌套与组合

struct 可以包含其他 struct:

mojo
@fieldwise_init
struct Line(Copyable):
    var start: Vec2
    var end: Vec2

    def length(self) -> Float64:
        var dx = self.end.x - self.start.x
        var dy = self.end.y - self.start.y
        return (dx * dx + dy * dy) ** 0.5

注意:struct 不能直接包含自身(无限大小)。链表、树这类自引用结构需要用指针(UnsafePointer / Pointer),属于进阶话题。

六、方法中的 self 约定速查

形式含义
def method(self, ...)只读访问(默认不可变引用)
def method(mut self, ...)需要修改字段时
def __init__(out self, ...)构造:self 待初始化
@staticmethod静态方法,无 self

七、小结

  • struct = 编译期静态绑定的自定义类型,零成本抽象的载体
  • 首选 @fieldwise_init 自动生成构造,特殊逻辑才手写 __init__(out self, ...)
  • 能力通过「实现 trait + dunder 方法」组合获得:CopyableMovableStringable……
  • 运算符重载与 Python 同构,迁移心智成本低

下一篇:trait 特征系统。

MIT License.