R中为mesh3d子类定义shade3d方法:是否可使用:::调用隐藏函数?
问题:为
mesh3d创建S3子类并修改shade3d默认参数的最佳实践 我想要创建mesh3d的S3子类,并为rgl::shade3d编写对应的方法。新方法基于现有shade3d函数,但要修改默认参数。最初的写法因递归调用导致栈溢出错误,改用rgl:::shade3d.mesh3d调用隐藏方法后问题解决,但了解到:::并非最佳实践,询问是否有替代方案,或该场景下使用:::是否可接受。
代码示例
library(rgl) # 创建测试对象 obj <- translate3d(tetrahedron3d(col = "red"), 0, 0, 0) # 创建新的S3子类 obj <- structure(obj, class = c("myclass", "mesh3d", "shape3d")) # 初始写法(报错) shade3d.myclass <- function(mesh, ...) { shade3d(mesh, ..., lit = F) } shade3d(obj) # 错误:C stack usage 15923488 is too close to the limit # 修改后可运行的写法 methods(shade3d) # [1] shade3d.mesh3d* shade3d.myclass shade3d.shapelist3d* shade3d.myclass <- function(mesh, ...) { rgl:::shade3d.mesh3d(mesh, ..., lit = F) } shade3d(obj)
解决方案
1. 递归报错原因
最初的写法中,调用shade3d(mesh, ..., lit = F)时,因为mesh的类是myclass,会反复触发shade3d.myclass,形成无限递归,最终导致栈溢出。
2. 推荐替代方案
方案一:临时修改对象类调用基类方法
临时将对象的类切换为mesh3d,调用完shade3d后再恢复原始类,这样会触发shade3d.mesh3d方法:
shade3d.myclass <- function(mesh, ...) { # 保存原始类 original_class <- class(mesh) # 临时切换为mesh3d类 class(mesh) <- "mesh3d" # 调用基类方法 result <- shade3d(mesh, ..., lit = FALSE) # 恢复原始类 class(mesh) <- original_class result }
方案二:使用NextMethod()
利用S3方法的NextMethod()机制,自动调用类向量中下一匹配类(即mesh3d)的方法,同时传递修改后的参数:
shade3d.myclass <- function(mesh, ..., lit = FALSE) { NextMethod() }
这个写法更简洁,且符合S3方法的设计规范。
3. 关于:::的使用说明
rgl:::shade3d.mesh3d是包内部未导出的方法,使用:::确实存在风险:包作者可能在后续版本中修改、重命名或移除该内部方法,导致你的代码出现兼容性问题。除非你能确认该内部方法长期稳定,否则优先选择上述两种替代方案。
内容的提问来源于stack exchange,提问作者user2390246
相关产品推荐
相关产品推荐

