联合类型

定义联合类型

V的联合类型在V编译器代码中大量采用。

有些使用接口的场景,不一定要全部用接口来实现,使用联合类型的代码看起来更简洁,清晰。

相对于go和rust来说,联合类型给V加分不少,用起来很舒服。

语法类似typescript,使用type 和 | 来定义一个联合类型:

 //定义联合类型,表示类型Expr可以是这几种类型的其中一种
type Expr = Foo | BoolExpr |  BinExpr | UnaryExpr

使用pub关键字,定义公共的联合类型:

pub type Expr = Foo | BoolExpr |  BinExpr | UnaryExpr

使用场景

联合类型相对于接口来说,比较适合于一个类型是已知的几种类型的其中一种,已知类型的数量是有限的,固定的,相对封闭的,不需要考虑未知类型的扩展性。

比如x.json2模块中,使用联合类型来包含所有json的节点类型,json节点类型种类是相对固定的,使用了联合类型这种数据结构来表示,后续的代码就变得很简洁清晰:

//代码位置:vlib/x/json2/decoder.v
pub type Any = string | int | i64 | f32 | f64 | any_int | any_float | bool | Null | []Any | map[string]Any

还有另一个最大的场景就是V编译器自身,使用了联合类型来包含所有的AST抽象语法树的类型,毕竟AST的节点类型也是有限的,固定的,相对封闭的,后续AST的逻辑代码也变得简洁清晰很多:

//代码位置:vlib/v/ast/ast.v
pub type TypeDecl = AliasTypeDecl | FnTypeDecl | SumTypeDecl | UnionSumTypeDecl

pub type Expr = AnonFn | ArrayInit | AsCast | Assoc | AtExpr | BoolLiteral | CTempVar |
	CallExpr | CastExpr | ChanInit | CharLiteral | Comment | ComptimeCall | ConcatExpr | EnumVal |
	FloatLiteral | Ident | IfExpr | IfGuardExpr | IndexExpr | InfixExpr | IntegerLiteral |
	Likely | LockExpr | MapInit | MatchExpr | None | OrExpr | ParExpr | PostfixExpr | PrefixExpr |
	RangeExpr | SelectExpr | SelectorExpr | SizeOf | SqlExpr | StringInterLiteral | StringLiteral |
	StructInit | Type | TypeOf | UnsafeExpr

pub type Stmt = AssertStmt | AssignStmt | Block | BranchStmt | CompFor | ConstDecl | DeferStmt |
	EnumDecl | ExprStmt | FnDecl | ForCStmt | ForInStmt | ForStmt | GlobalDecl | GoStmt |
	GotoLabel | GotoStmt | HashStmt | Import | InterfaceDecl | Module | Return | SqlStmt |
	StructDecl | TypeDecl

而接口更适合用来支持未知类型的扩展性。

使用联合类型

  • 联合类型作为函数的参数或返回值,可以作为变量声明,结构体字段。

  • 使用match语句,进行类型的进一步判断。

  • 使用match语句,如果需要修改联合类型的值需要在变量前加mut。

  • 使用is关键字联合类型具体是哪一种类型。

  • 使用as关键字将联合类型转换为另一种类型,当然要转换的类型在联合类型定义的类型范围内。

获取联合类型的具体类型

联合类型使用内置方法type_name()来返回变量的具体类型。

联合类型相等判断

for is类型循环判断

用于联合类型的类型循环判断(感觉没啥用,就是一个语法糖而已):

as类型转换

可以通过as将联合类型显式转换为具体的类型,如果转换类型不成功,则报错:V panic: as cast: cannot cast。

联合类型嵌套

联合类型还可以嵌套使用,支持更复杂的场景:

联合类型方法

可以像结构体那样,给联合类型添加方法:

联合类型注解

联合类型也可以像结构体那样增加自定义注解,然后解析并使用,具体可参考注解章节

泛型联合类型

联合类型也支持泛型的结合使用。

具体参考章节:泛型

访问公共字段

联合类型可以在方法中访问所有类型的公共字段,并且支持联合类型的多级嵌套。

截图中是V编译器中的例子:stmt.pos是所有Stmt联合类型的公共字段,有了这个特性以后,代码就可以简洁到像截图中的第一个方法那样:

图像

联合类型作为结构体字段

结构体字段的类型也可以是联合体类型:

子类不允许是指针类型

使用联合类型时,有一点需要注意:联合类型的子类中不允许出现指针类型,编译器会检查并报错。

最后更新于

这有帮助吗?