有人可以解释为什么 R 为该对象的超级 class 而不是子 class 调度 S3 方法吗?
Can someone explain why R dispatches the S3 method for this object's super class rather than the sub class?
在这个例子中,包命名空间和 S3 调度有一些我无法理解的微妙之处。对这个问题有深入了解的人可以用简单的术语向我解释一下,为什么 R 为这个对象调度 as.tags.htmlwidget
而不是 as.tags.rdeckControls
?
library(rdeck.controls) ##remotes::install_github("qfes/rdeck.controls")
library(htmltools)
library(sloop)
library(purrr)
foo_widget <-
structure(list(x = list(targetRDeckId = "mitigation_activity",
controlType = "dropdown", controlData = list(layerNames = c("Mitigation activity: All",
"Mitigation activity: Community Education", "Mitigation activity: Fire Breaks or Trails",
"Mitigation activity: Hazard Reduction"), layerGroupNames = character(0),
initialSelection = "Mitigation activity: All", label = "")),
width = "100%", height = "1em !important", sizingPolicy = list(
defaultWidth = NULL, defaultHeight = NULL, padding =
NULL,
viewer = list(defaultWidth = NULL, defaultHeight = NULL,
padding = NULL, fill = TRUE, suppress = FALSE, paneHeight = NULL),
browser = list(defaultWidth = NULL, defaultHeight = NULL,
padding = NULL, fill = FALSE, external = FALSE),
knitr = list(defaultWidth = NULL, defaultHeight = NULL,
figure = TRUE)), dependencies = NULL, elementId = NULL,
preRenderHook = NULL, jsHooks = list()), class = c("rdeckControls",
"htmlwidget"), package = "rdeck.controls")
methods("as.tags")
#> [1] as.tags.character* as.tags.default*
#> [3] as.tags.html* as.tags.html_dependency*
#> [5] as.tags.htmlwidget* as.tags.list*
#> [7] as.tags.rdeckControls as.tags.shiny.tag*
#> [9] as.tags.shiny.tag.function* as.tags.shiny.tag.list*
#> see '?methods' for accessing help and source code
s3_dispatch(as.tags(foo_widget))
#> => as.tags.rdeckControls
#> * as.tags.htmlwidget
#> * as.tags.default
error <- purrr::safely(function(x) as.tags(foo_widget))(foo_widget)
error
#> $result
#> NULL
#>
#> $error
#> <simpleError in validateCssUnit(sizeInfo$height): "1em !important" is not a valid CSS unit (e.g., "100%", "400px", "auto")>
#
# this means as.tags.htmlWidget was run
#
str(as.tags.rdeckControls(foo_widget))
#> List of 3
#> $ :List of 3
#> ..$ : NULL
#> ..$ :List of 3
#> .. ..$ name : chr "div"
#> .. ..$ attribs :List of 3
#> .. .. ..$ id : chr "htmlwidget-debd00a6269d494de569"
#> .. .. ..$ style: chr "width:100%;height:1em !important;"
#> .. .. ..$ class: chr "rdeckControls html-widget"
#> .. ..$ children: list()
#> .. ..- attr(*, "class")= chr "shiny.tag"
#> ..$ : NULL
#> ..- attr(*, "class")= chr [1:2] "shiny.tag.list" "list"
#> $ :List of 3
#> ..$ name : chr "script"
#> ..$ attribs :List of 2
#> .. ..$ type : chr "application/json"
#> .. ..$ data-for: chr "htmlwidget-debd00a6269d494de569"
#> ..$ children:List of 1
#> .. ..$ : 'html' chr "{\"x\":{\"targetRDeckId\":\"mitigation_activity\",\"controlType\":\"dropdown\",\"controlData\":{\"layerNames\":"| __truncated__
#> .. .. ..- attr(*, "html")= logi TRUE
#> ..- attr(*, "class")= chr "shiny.tag"
#> $ : NULL
#> - attr(*, "class")= chr [1:2] "shiny.tag.list" "list"
#> - attr(*, "html_dependencies")=List of 2
#> ..$ :List of 10
#> .. ..$ name : chr "htmlwidgets"
#> .. ..$ version : chr "1.5.3"
#> .. ..$ src :List of 1
#> .. .. ..$ file: chr "C:/Users/msmcbain/libs/R/htmlwidgets/www"
#> .. ..$ meta : NULL
#> .. ..$ script : chr "htmlwidgets.js"
#> .. ..$ stylesheet: NULL
#> .. ..$ head : NULL
#> .. ..$ attachment: NULL
#> .. ..$ package : NULL
#> .. ..$ all_files : logi TRUE
#> .. ..- attr(*, "class")= chr "html_dependency"
#> ..$ :List of 10
#> .. ..$ name : chr "rdeckControls-binding"
#> .. ..$ version : chr "0.2.0"
#> .. ..$ src :List of 1
#> .. .. ..$ file: chr "C:/Users/msmcbain/libs/R/rdeck.controls/htmlwidgets"
#> .. ..$ meta : NULL
#> .. ..$ script : chr "rdeckControls.js"
#> .. ..$ stylesheet: NULL
#> .. ..$ head : NULL
#> .. ..$ attachment: NULL
#> .. ..$ package : NULL
#> .. ..$ all_files : logi FALSE
#> .. ..- attr(*, "class")= chr "html_dependency"
#> - attr(*, "browsable_html")= logi TRUE
#
# This works if called directly
#
as.tags.rdeckControls <- function(x) as.character(x)
as.tags(foo_widget)
#> [1] "list(targetRDeckId = \"mitigation_activity\", controlType = \"dropdown\", controlData = list(layerNames = c(\"Mitigation activity: All\", \"Mitigation activity: Community Education\", \"Mitigation activity: Fire Breaks or Trails\", \"Mitigation activity: Hazard Reduction\"), layerGroupNames = character(0), initialSelection = \"Mitigation activity: All\", label = \"\"))"
#> [2] "100%"
#> [3] "1em !important"
#> [4] "list(defaultWidth = NULL, defaultHeight = NULL, padding = NULL, viewer = list(defaultWidth = NULL, defaultHeight = NULL, padding = NULL, fill = TRUE, suppress = FALSE, paneHeight = NULL), browser = list(defaultWidth = NULL, defaultHeight = NULL, padding = NULL, fill = FALSE, external = FALSE), knitr = list(defaultWidth = NULL, defaultHeight = NULL, figure = TRUE))"
#> [5] "NULL"
#> [6] "NULL"
#> [7] "NULL"
#> [8] "list()"
#
# and if defined locally
由 reprex package (v2.0.0)
于 2021-07-08 创建
您的 NAMESPACE 文件没有将该方法声明为 S3 方法。也不需要显式导出它(大多数 S3 方法不导出)。
所以而不是
export(as.tags.rdeckControls)
你应该
S3method(as.tags, rdeckControls)
roxygen 应该会在大部分时间为您解决这个问题。这里的问题可能是它无法分辨什么是函数名和什么是 class 因为函数名中有额外的 .
。你应该能够用
来消除歧义
@method as.tags rdeckControls
记录该功能时。
在这个例子中,包命名空间和 S3 调度有一些我无法理解的微妙之处。对这个问题有深入了解的人可以用简单的术语向我解释一下,为什么 R 为这个对象调度 as.tags.htmlwidget
而不是 as.tags.rdeckControls
?
library(rdeck.controls) ##remotes::install_github("qfes/rdeck.controls")
library(htmltools)
library(sloop)
library(purrr)
foo_widget <-
structure(list(x = list(targetRDeckId = "mitigation_activity",
controlType = "dropdown", controlData = list(layerNames = c("Mitigation activity: All",
"Mitigation activity: Community Education", "Mitigation activity: Fire Breaks or Trails",
"Mitigation activity: Hazard Reduction"), layerGroupNames = character(0),
initialSelection = "Mitigation activity: All", label = "")),
width = "100%", height = "1em !important", sizingPolicy = list(
defaultWidth = NULL, defaultHeight = NULL, padding =
NULL,
viewer = list(defaultWidth = NULL, defaultHeight = NULL,
padding = NULL, fill = TRUE, suppress = FALSE, paneHeight = NULL),
browser = list(defaultWidth = NULL, defaultHeight = NULL,
padding = NULL, fill = FALSE, external = FALSE),
knitr = list(defaultWidth = NULL, defaultHeight = NULL,
figure = TRUE)), dependencies = NULL, elementId = NULL,
preRenderHook = NULL, jsHooks = list()), class = c("rdeckControls",
"htmlwidget"), package = "rdeck.controls")
methods("as.tags")
#> [1] as.tags.character* as.tags.default*
#> [3] as.tags.html* as.tags.html_dependency*
#> [5] as.tags.htmlwidget* as.tags.list*
#> [7] as.tags.rdeckControls as.tags.shiny.tag*
#> [9] as.tags.shiny.tag.function* as.tags.shiny.tag.list*
#> see '?methods' for accessing help and source code
s3_dispatch(as.tags(foo_widget))
#> => as.tags.rdeckControls
#> * as.tags.htmlwidget
#> * as.tags.default
error <- purrr::safely(function(x) as.tags(foo_widget))(foo_widget)
error
#> $result
#> NULL
#>
#> $error
#> <simpleError in validateCssUnit(sizeInfo$height): "1em !important" is not a valid CSS unit (e.g., "100%", "400px", "auto")>
#
# this means as.tags.htmlWidget was run
#
str(as.tags.rdeckControls(foo_widget))
#> List of 3
#> $ :List of 3
#> ..$ : NULL
#> ..$ :List of 3
#> .. ..$ name : chr "div"
#> .. ..$ attribs :List of 3
#> .. .. ..$ id : chr "htmlwidget-debd00a6269d494de569"
#> .. .. ..$ style: chr "width:100%;height:1em !important;"
#> .. .. ..$ class: chr "rdeckControls html-widget"
#> .. ..$ children: list()
#> .. ..- attr(*, "class")= chr "shiny.tag"
#> ..$ : NULL
#> ..- attr(*, "class")= chr [1:2] "shiny.tag.list" "list"
#> $ :List of 3
#> ..$ name : chr "script"
#> ..$ attribs :List of 2
#> .. ..$ type : chr "application/json"
#> .. ..$ data-for: chr "htmlwidget-debd00a6269d494de569"
#> ..$ children:List of 1
#> .. ..$ : 'html' chr "{\"x\":{\"targetRDeckId\":\"mitigation_activity\",\"controlType\":\"dropdown\",\"controlData\":{\"layerNames\":"| __truncated__
#> .. .. ..- attr(*, "html")= logi TRUE
#> ..- attr(*, "class")= chr "shiny.tag"
#> $ : NULL
#> - attr(*, "class")= chr [1:2] "shiny.tag.list" "list"
#> - attr(*, "html_dependencies")=List of 2
#> ..$ :List of 10
#> .. ..$ name : chr "htmlwidgets"
#> .. ..$ version : chr "1.5.3"
#> .. ..$ src :List of 1
#> .. .. ..$ file: chr "C:/Users/msmcbain/libs/R/htmlwidgets/www"
#> .. ..$ meta : NULL
#> .. ..$ script : chr "htmlwidgets.js"
#> .. ..$ stylesheet: NULL
#> .. ..$ head : NULL
#> .. ..$ attachment: NULL
#> .. ..$ package : NULL
#> .. ..$ all_files : logi TRUE
#> .. ..- attr(*, "class")= chr "html_dependency"
#> ..$ :List of 10
#> .. ..$ name : chr "rdeckControls-binding"
#> .. ..$ version : chr "0.2.0"
#> .. ..$ src :List of 1
#> .. .. ..$ file: chr "C:/Users/msmcbain/libs/R/rdeck.controls/htmlwidgets"
#> .. ..$ meta : NULL
#> .. ..$ script : chr "rdeckControls.js"
#> .. ..$ stylesheet: NULL
#> .. ..$ head : NULL
#> .. ..$ attachment: NULL
#> .. ..$ package : NULL
#> .. ..$ all_files : logi FALSE
#> .. ..- attr(*, "class")= chr "html_dependency"
#> - attr(*, "browsable_html")= logi TRUE
#
# This works if called directly
#
as.tags.rdeckControls <- function(x) as.character(x)
as.tags(foo_widget)
#> [1] "list(targetRDeckId = \"mitigation_activity\", controlType = \"dropdown\", controlData = list(layerNames = c(\"Mitigation activity: All\", \"Mitigation activity: Community Education\", \"Mitigation activity: Fire Breaks or Trails\", \"Mitigation activity: Hazard Reduction\"), layerGroupNames = character(0), initialSelection = \"Mitigation activity: All\", label = \"\"))"
#> [2] "100%"
#> [3] "1em !important"
#> [4] "list(defaultWidth = NULL, defaultHeight = NULL, padding = NULL, viewer = list(defaultWidth = NULL, defaultHeight = NULL, padding = NULL, fill = TRUE, suppress = FALSE, paneHeight = NULL), browser = list(defaultWidth = NULL, defaultHeight = NULL, padding = NULL, fill = FALSE, external = FALSE), knitr = list(defaultWidth = NULL, defaultHeight = NULL, figure = TRUE))"
#> [5] "NULL"
#> [6] "NULL"
#> [7] "NULL"
#> [8] "list()"
#
# and if defined locally
由 reprex package (v2.0.0)
于 2021-07-08 创建您的 NAMESPACE 文件没有将该方法声明为 S3 方法。也不需要显式导出它(大多数 S3 方法不导出)。
所以而不是
export(as.tags.rdeckControls)
你应该
S3method(as.tags, rdeckControls)
roxygen 应该会在大部分时间为您解决这个问题。这里的问题可能是它无法分辨什么是函数名和什么是 class 因为函数名中有额外的 .
。你应该能够用
@method as.tags rdeckControls
记录该功能时。