Nim学习:Object
2025-07-01 20:55:10
#定义对象类型
定义对象类型有三种形式:
objectref objectptr object
#object
1 | type |
本质上就是结构体,从生成的 C 代码中可看出来:
1 | struct tyObject_MyObj1__inljzvlFXKezToqKwQKx9bg { |
区别在使用上,例子:
1 | proc foo1() = |
这是对应的 C 代码,为了方便理解删除了一些无关的代码:
1 | N_LIB_PRIVATE N_NIMCALL(void, foo1__main_u9)(void) { |
从代码中可以看出来,object声明的对象默认在栈上分配,初始化会清零。如果改用new分配则会在堆上,且会被 GC 回收:
1 | N_LIB_PRIVATE N_NIMCALL(void, foo1__main_u9)(void) { |
#ref object
使用ref关键字定义对象总是在堆上分配:
1 | type |
程序运行会报错:SIGSEGV: Illegal storage access. (Attempt to read from nil?)。
看看对应的 C 代码:
1 | N_LIB_PRIVATE N_NIMCALL(void, foo1__main_u9)(void) { |
错误原因就是访问空指针了,所以ref object必须用new关键字分配,同时它会被 GC 回收。
#ptr object
ptr object和ref object一样都是指针类型,但ptr object不会被 GC 回收,需要手动管理生命周期:
1 | proc foo1() = |
和 C 一样,申请一块内存然后强制转换为类型指针。不过一般不会这么用。
#不显示使用 ref 或 ptr 关键字
实际上,可以不在定义类型时用ref或ptr关键字,而是在声明变量时决定其类型,这样更灵活:
1 | var obj1: ref MyObj1 |
记住:
创建对象主要用以下几种方法:
| 函数 | 释放内存 | 初始化清零 | 说明 |
|---|---|---|---|
| new | GC | 是 | |
| create | dealloc | 是 | |
| createU | dealloc | 否 | |
| createShared | freeShared | 是 | 在共享堆上分配 |
| createSharedU | freeShared | 否 | 在共享堆上分配 |
另外,在定义类型是用ref或ptr是有意义的,这可以强制要求对象在堆上分配,比如在与 C 交互时,对象的生命周期由用户控制。
#RootObj
RootObj 是什么?简单一句话就是:当你要实现类的多态性时就要从它继承。
1 | type |
#函数参数类型
看例子:
1 | type |
从这段代码得到的知识点:
- 如果参数是值类型,默认不可修改成员变量。要修改的化需要用
var关键字。 - 如果是
ref或ptr类型则可以直接修改成员变量而不需要var关键字。 new创建的是ref类型,create创建的是ptr类型。- 如果类型需要支持用
create创建,则在定义时不要加ptr(示例中的 MyObj3 类型),否则会得到一个二级指针。
1 | type |
#相关阅读
Nim Tutorial (Part II)
Object Oriented Programming
Why inherit RootObj?