rust - 结构继承
问题描述
C 中的典型 AST 实现可能如下所示:
typedef enum {
AST_IDENT,
AST_STRING,
} Ast_Tag;
typedef struct { Ast_Tag tag; u32 flags; } Ast;
typedef struct { Ast base; Intern *name; } Ast_Ident;
typedef struct { Ast base; Intern *str; } Ast_String;
// A function that downcasts to the derived type:
void foo (Ast *node) {
switch (node->tag) {
case AST_IDENT: {
Ast_Ident *ident = (Ast_Ident*)node;
do_something_with_name(ident->name);
} break;
case AST_STRING: {
Ast_String *str = (Ast_String*)node;
do_something_with_name(str->name);
} break;
}
}
// A function that upcasts to the base type:
void bar (Ast_Ident *ident) {
foo((Ast*)ident);
}
有没有办法在生锈中做到这一点?我想向下转换会特别成问题。
注意:我不是在问如何实现 AST,而是在问如何复制结构继承,如上所示。
编辑:很抱歉造成混乱。这里的要点是使用结构继承是为了避免使每个节点都具有相同的大小,因此枚举不是一种选择。
解决方案
你基本上实现了 Rustenum
变体:
struct Ast {
flags: u32,
kind: AstKind,
}
enum AstKind {
Ident(String),
String(String),
}
fn foo(ast: Ast) {
match ast.kind {
AstKind::Ident(ident) => println!("flags: {:?}, ident: {:?}", ast.flags, ident),
AstKind::String(s) => println!("string: {:?}, ident: {:?}", ast.flags, s),
}
}
fn bar(flags: u32, ident: String) {
foo(Ast {
flags,
kind: AstKind::Ident(ident),
})
}
fn main() {
bar(42, "MisterMV".into())
}
您似乎关心大小:
这里的要点是使用结构继承是为了避免使每个节点都具有相同的大小,因此枚举不是一种选择。
这通常不是问题,clippy 有一个 lint 调用large_enum_variant
,有一个合理的默认值,您可以更改它。Clippy 也提出了一个合理的解决方案:
enum AstKind {
Ident(Box<Big>),
String(Small),
}
还有其他答案已经涵盖的其他选择。
推荐阅读
- json - 用 jq 连接 json 数组对象
- python - Selenium 登录看起来可以正常工作,但是 BeautifulSoup 输出显示登录页面
- angular - 我找不到与我的项目 @angular/core 5.2.8 兼容的 ngx-Permission 版本
- python - Django & Python : 通过添加分隔符以 django 形式格式化 FloatField
- django - 根据某些模型日期字段运行 Django Celery Beat 任务
- apache-spark - 生成空 spark DF 提供了一个包含列名的列表
- genexus - 如何在网格上编写 Option Distinct
- ios - 照片扩展:无法保存未“向上”定向的图像
- r - 加快对称矩阵的计算;外用
- c++ - 解决 ns3 数据包接收问题