Mojo 学习 —— 结构体

Mojo 学习 —— 结构体


Mojo 的结构体是一种数据结构,可以对抽象概念(如数据类型或对象)的字段和方法进行封装。

字段是变量,用于保存与结构体相关的数据;方法是结构体内部的函数,通常用于处理字段数据。

在大多数情况下,Mojo 的结构体格式旨在为程序中使用的高级数据类型提供静态、内存安全的数据结构。

Mojo 标准库中的所有数据类型(如 IntBoolStringTuple 等)都定义为结构体。

从前面的函数章节中,我们可以发现 Mojodef 函数中提供了动态编程功能,同时在 fn 函数中加强代码安全性。

而对于结构体,Mojo 更倾向于安全的一面,虽然可以在结构体中使用 deffn 声明函数,但所有的字段都必须使用 var 来声明

定义结构体

我们可以定义一个简单的结构体,只包含两个字段:

struct MyPair:
    var first: Int
    var second: Int

但是,由于该结构体没有构造函数,所以无法用其来实例化对象。类似于 Python,我们可以定义一个 __init__ 构造函数

struct MyPair:
    var first: Int
    var second: Int

    fn __init__(inout self, first: Int, second: Int):
        self.first = first
        self.second = second

请注意,__init__ 方法的第一个参数是 inout self,声明了 self 是一个可变引用

self 必须是第一个参数,它引用了当前的结构体实例。在调用构造函数时,你无需为 self 传递值,Mojo 会自动将其传递进来。

__init__ 方法是许多预定义的特殊方法之一,Mojo 中有许多与 Pythonclass 中一样的用双下划线开头和结尾的特殊方法,像 __str____repr__

声明字段时不能对其赋值,您必须在构造函数中初始化结构体的所有字段。(如果不初始化字段,代码将无法编译)。

一旦你有了一个构造函数,就可以创建一个 MyPair 的实例,例如

var mine = MyPair(2,4)
print(mine.first)

定义方法

除了像 __init__ 这样的特殊方法外,您还可以在结构体中添加任何其他方法。例如

struct MyPair:
    var first: Int
    var second: Int

    fn __init__(inout self, first: Int, second: Int):
        self.first = first
        self.second = second

    fn get_sum(self) -> Int:
        return self.first + self.second

调用函数会打印一个 14

var mine = MyPair(6, 8)
print(mine.get_sum())

请注意,get_sum 也使用了 self 参数,这是在方法中访问结构体字段的唯一途径。self 只是一个约定俗成的名称,你可以替换成任何你想要的名称

使用隐式 self 参数的方法被称为实例方法,它们会作用于结构体的实例上

注意

结构体方法中的 self 参数是 fn 函数中唯一不需要类型的参数。如果你愿意,你也可以指定,但一般都会省略它,因为 Mojo 知道它是什么类型(本例中为 MyPair)。

静态方法

结构体也可以有静态方法。静态方法可以在不创建结构体实例的情况下调用,即可以直接使用结构体名称调用的函数。

与实例方法不同,静态方法不接收隐式 self 参数,因此不能访问结构体上的任何字段。

要声明静态方法,请使用 @staticmethod 装饰器,并且不要包含 self 参数:

struct Logger:

    fn __init__(inout self):
        pass

    @staticmethod
    fn log_info(message: String):
        print("Info: ", message)

您可以在结构体上调用静态方法,也可以在类型的实例上调用。两种形式如下所示:

Logger.log_info("Static method called.")
var l = Logger()
l.log_info("Static method called from instance.")

将会输出

Static method called.
Static method called from instance.

结构体与类的比较

如果您熟悉其他面向对象语言,那么结构体看起来很像类,两者有相似之处,但也有一定的区别。

Mojo 后面还会添加对类类的支持,以匹配 Python 类的行为。

Mojo 结构体和 Python 类之间的的共同之处在于,它们都支持方法、字段、操作符重载以及用于元编程的装饰器等,但主要区别如下:

  • Python 类是动态的,它们允许在运行时进行动态派发、monkey-patching(或 swizzling)和动态绑定实例字段
  • Mojo 结构体是静态的,它们在编译时被绑定(不能在运行时添加方法)。用灵活性换取性能,同时又安全易用
  • Mojo 结构不支持继承,但结构可以实现 trait
  • Python 类支持类属性,即类的所有实例共享的值,相当于其他语言中的类变量或静态数据成员
  • Mojo 结构不支持静态数据成员

在语法上,与 Python 类最大的不同是,结构体中的所有字段都必须用 var 明确声明

Mojo 中,结构体的结构和内容在编译时就已经确定,程序运行时无法更改。而在 Python 中,可以动态添加、删除或更改对象的属性

不过,结构体的静态特性有助于 Mojo 更快地运行代码。程序可以准确地知道在哪里找到结构体的信息以及如何使用它,而不会在运行时出现任何额外的步骤或延迟。

前面也说到,Mojo 的所有标准类型(IntString 等)都是用结构体创建的,而不是硬连接到语言本身。

这让你在编写代码时拥有更多的灵活性和控制权,也意味着你可以定义自己的类型,并拥有所有相同的功能

特殊方法

这里所说的特殊方法也就是 Python 中所说的 魔法方法,是具有特殊功能的方法,如构造函数方法 __init__

虽然这些特殊方法可以通过方法名来调用,但是你绝对不应该这样做

例如,在创建结构体实例时,Mojo 会调用 __init__ 方法;当 Mojo 销毁实例时,它会调用 __del__ 方法(如果它存在的话)

一些内置的操作符(+<==| 等)也是作为特殊方法实现的,Mojo 会隐式地调用这些方法

Mojo 支持的特殊方法与 Python 的所有特殊方法相匹配,而且通常具有下面两种功能的其中一种

  • 操作符重载:

用于为结构体添加一些运算操作,如 <+|

  • 处理生命周期事件:

这些特殊方法主要用于处理实例的生命周期和值所有权。例如,__init____del__ 标志着实例生命周期的开始和结束

大多数结构体都是其他类型的简单聚合,因此除非您的类型在创建、复制、移动或销毁实例时需要自定义行为,否则您可以通过添加 @value 装饰器来合成所需的基本生命周期方法(并为自己节省一些时间)。

@value 装饰器

当你为结构体添加 @value 装饰器时,Mojo 会为结构体添加基本的生命周期方法,使你的对象提供完整的值语义。

具体来说,它会生成 __init__, __copyinit____moveinit__ 方法,这些方法允许你以符合值语义并与 Mojo 所有权模型兼容的方式构造、复制和移动你的结构类型。

例如

@value
struct MyPet:
    var name: String
    var age: Int

Mojo 会注意到你没有成员构造函数、移动或复制构造函数,它会为你合成这些,就像下面的代码这样

struct MyPet:
    var name: String
    var age: Int

    fn __init__(inout self, owned name: String, age: Int):
        self.name = name^
        self.age = age

    fn __copyinit__(inout self, existing: Self):
        self.name = existing.name
        self.age = existing.age

    fn __moveinit__(inout self, owned existing: Self):
        self.name = existing.name^
        self.age = existing.age

如果没有复制和移动构造函数,Mojo 不知道如何复制与移动 MyPet 的实例,下面的代码将会报错

var dog = MyPet("Charlie", 5)
var poodle = dog
print(poodle.name)

添加 @value 装饰器后,Mojo 只会为你添加未定义的构造函数,也就是说,你还是可以为每个方法实现自定义的版本

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

名本无名

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

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

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

打赏作者

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

抵扣说明:

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

余额充值