Crystal语言中**(Double splat双星号)的作用与使用方法
Crystal 方法定义与调用中
**(双星号展开)的作用 ** 即 double splat(双星号展开),在Crystal中有两类核心用法,结合给出的Shrine上传库代码示例说明如下:
示例参考代码:
class FileImport::AssetUploader < Shrine def generate_location(io : IO | UploadedFile, metadata, context, **options) name = super(io, metadata, **options) File.join("imports", context[:model].id.to_s, name) end end FileImport::AssetUploader.upload(file, "store", context: { model: YOUR_ORM_MODEL })
1. 方法定义场景:捕获剩余命名参数
在方法定义的参数列表末尾使用**参数名的写法(语法要求该参数必须放在形参列表最后),会自动接收所有调用时传入、未被前面显式声明的形参匹配到的命名参数,统一封装为NamedTuple类型赋值给**后命名的变量。
- 对应示例中
generate_location方法的**options:Shrine父类的generate_location原生支持多个可选命名参数(比如自定义文件名、扩展名处理规则等),子类重写方法时不需要把所有可选参数逐一在形参里列全,靠**options就能把所有额外传入的命名参数全部接住,不会触发参数不匹配的编译错误。
2. 方法调用场景:展开键值对为命名参数
在调用方法传参时,给键类型匹配的NamedTuple/Hash类型变量前加**,会把变量内的所有键值对展开为独立的命名参数传入目标方法。
- 对应示例中
super(io, metadata, **options)的写法:调用父类同名原始实现时,不需要把options里存储的每个键值对手动拆分逐一传参,用**options就能把之前捕获到的所有额外命名参数原封不动透传给父类逻辑,既不会漏传参数,也省掉了大量冗余的参数透传代码。
这种写法在重写框架方法的场景下兼容性极强:哪怕后续框架版本给父类方法新增了可选命名参数,子类重写的逻辑不需要做任何修改,就能自动接收、透传新参数,不会出现参数匹配报错。示例最后调用upload方法时传入的context: { model: YOUR_ORM_MODEL }就是普通命名参数传参,这个值会沿着Shrine的内部调用链传到generate_location的context形参中,供自定义路径逻辑拼接模型ID使用。
内容的提问来源于stack exchange,提问作者learncodes123
相关产品推荐
相关产品推荐

