如何在R6类中实现S3方法分派?现有代码报错求解
在R6类中实现基于参数类型的方法分派
你的代码报错是因为S3的UseMethod会在泛型函数所在的命名空间或全局环境中查找对应方法,但你在R6类内部定义的divide.list和divide.data.frame是类的成员函数,不在UseMethod的查找路径里,所以无法匹配到方法。
下面提供几种可行的解决方案,不局限于S3分派:
解决方案一:使用全局S3泛型与方法
将divide泛型和对应类型的方法定义在全局环境,R6类直接调用这个全局泛型:
# 定义全局S3泛型及方法 divide <- function(x) UseMethod("divide") divide.list <- function(x) x$x/4 divide.data.frame <- function(x) x$x/2 # R6类调用全局泛型 tmp <- R6::R6Class("tmp", list( a = list(x = 1), b = data.frame(x = 1), test_list = function() divide(self$a), test_df = function() divide(self$b) ) ) tmp2 <- tmp$new() tmp2$test_df() #> [1] 0.5 tmp2$test_list() #> [1] 0.25
解决方案二:R6类内部手动实现分派(推荐,完全封装)
不依赖S3的UseMethod,直接在类内通过判断参数类型调用对应方法,逻辑完全封装在类内部:
tmp <- R6::R6Class("tmp", list( a = list(x = 1), b = data.frame(x = 1), # 主分派方法 divide = function(x) { if (inherits(x, "data.frame")) { self$divide_dataframe(x) } else if (inherits(x, "list")) { self$divide_list(x) } else { stop("No applicable method for 'divide'") } }, # 对应类型的内部方法 divide_list = function(x) x$x/4, divide_dataframe = function(x) x$x/2, test_list = function() self$divide(self$a), test_df = function() self$divide(self$b) ) ) tmp2 <- tmp$new() tmp2$test_df() #> [1] 0.5 tmp2$test_list() #> [1] 0.25
解决方案三:动态注册S3方法到全局环境
在R6类初始化时,将内部方法注册为全局S3方法,兼顾封装性与S3系统的使用:
# 先定义全局泛型 divide <- function(x) UseMethod("divide") tmp <- R6::R6Class("tmp", list( a = list(x = 1), b = data.frame(x = 1), initialize = function() { # 将类内方法注册为全局S3方法 assign("divide.list", self$divide_list, envir = .GlobalEnv) assign("divide.data.frame", self$divide_dataframe, envir = .GlobalEnv) }, divide_list = function(x) x$x/4, divide_dataframe = function(x) x$x/2, test_list = function() divide(self$a), test_df = function() divide(self$b) ) ) tmp2 <- tmp$new() tmp2$test_df() #> [1] 0.5 tmp2$test_list() #> [1] 0.25
内容的提问来源于stack exchange,提问作者Baraliuh
相关产品推荐
相关产品推荐

