R语言引用类继承中内部函数调用问题咨询
解决R包继承时未导出内部函数找不到的问题,及包内自引用
:::的注意事项 我正在开发两个R包:
- Package_A中定义了Reference Class
A,其方法myMethod2调用了包内未导出的内部函数.doSomeCheck - Package_B通过
contains = 'A'继承了A,实例化B后调用myMethod2会出现找不到.doSomeCheck的错误
已有的两种解决方案:
- 导出
.doSomeCheck函数,但会暴露内部实现 - 在
myMethod2中用Package_A:::.doSomeCheck()调用,但不够优雅
下面给出更合适的第三种方案,并说明包内使用:::自引用的注意事项:
第三种方案:将内部函数封装为类的私有方法
把原本的包级内部函数.doSomeCheck定义为classA的私有方法,利用Reference Class的内部作用域实现封装,子类继承后可正常调用,无需导出或使用:::。
修改后的Package_A代码:
#'@ export classA <- setRefClass( 'A', methods=list( myMethod1 = function() { # 方法逻辑 }, myMethod2 = function() { .self$.doSomeCheck() }, # 定义私有方法,以.开头遵循Reference Class私有约定 .doSomeCheck = function() { # 原内部函数的逻辑 } ) )
优势:
- 符合面向对象的封装原则,内部校验逻辑仅对类的方法可见,不对外暴露
- 子类
classB继承后,myMethod2可直接调用父类的私有方法,无需额外修改 - 避免了导出内部函数或使用
:::带来的问题,代码结构更清晰
包内使用:::自引用函数的注意事项
- CRAN合规性问题:CRAN不推荐在包内使用
:::访问自身的未导出对象,因为这会暴露内部实现细节,不符合包的接口设计规范,提交包时可能被拒绝。 - 版本兼容性风险:包的内部函数属于实现细节,后续版本迭代中可能被修改、重命名或删除,使用
:::自引用会让代码依赖这些不稳定的内部结构,降低包的兼容性。 - 可读性与维护性差:其他开发者阅读代码时,会疑惑为何要使用
:::调用自身包的函数,不如类方法或直接调用包内函数的方式直观,增加维护成本。 - 作用域问题根源:Reference Class方法的执行环境是实例的环境而非包的命名空间,所以直接调用包内未导出函数会找不到。虽然
:::能强制从包命名空间获取,但这是绕过作用域问题的权宜之计,而非最优解。
内容的提问来源于stack exchange,提问作者luigidolcetti
相关产品推荐
相关产品推荐

