# r s3

## 我期待的是：

TLDR; - 所有指示都是`as(4L, "numeric")`應該調度到一個函數，其主體使用`as.numeric(4L)`將其轉換為`"numeric"`向量。）

``````showMethods("coerce")
# Function: coerce (package methods)
# from="ANY", to="array"
#      ... snip ...
# from="ANY", to="numeric"
#      ... snip ...``````

``````getMethod("coerce", c("ANY", "numeric"))
# Method Definition:
#
# function (from, to, strict = TRUE)
# {
#     value <- as.numeric(from)
#     if (strict)
#         attributes(value) <- NULL
#     value
# }
# <environment: namespace:methods>
#
# Signatures:
#         from  to
# target  "ANY" "numeric"
# defined "ANY" "numeric"``````

``````## (1) There isn't (apparently!) any specific method for "integer"-->"numeric"
##     conversion
getMethod("coerce", c("integer", "numeric"))
# Error in getMethod("coerce", c("integer", "numeric")) :
#   no method found for function 'coerce' and signature integer, numeric

## (2) This says that the "ANY"-->"numeric" method will be used for "integer"-->"numeric"
##     conversion
selectMethod("coerce",  signature=c("integer", "numeric"))
# Method Definition:
#
# function (from, to, strict = TRUE)
# {
#     value <- as.numeric(from)
#     if (strict)
#         attributes(value) <- NULL
#     value
# }
# <environment: namespace:methods>
#
# Signatures:
#         from      to
# target  "integer" "numeric"
# defined "ANY"     "numeric"``````

## 實際發生了什麼：

TLDR;實際上，調用`as(4L, "numeric")`加載和調度到一個什麼都不做的方法。）

``````## (1) as.numeric() would do the job, but as(..., "numeric") does not
class(as(4L, "numeric"))
#[1] "integer"
class(as.numeric(4L))
# [1] "numeric"

## (2) Tracing shows that the "generic" method isn't called
trace("coerce", signature=c("ANY", "numeric"))

as(c(FALSE, TRUE), "numeric")        ## <-- It's called for "logical" vectors
# Tracing asMethod(object) on entry
# [1] 0 1

as(c("1", "2"), "numeric")           ## <-- and for "character" vectors
# Tracing asMethod(object) on entry
# [1] 1 2

as(c(1L, 2L), "numeric")             ## <-- but not for "integer" vectors
# [1] 1 2

untrace("coerce")``````

（在我們嘗試第一次`"integer"``"character"`轉換之前，將以下調用的結果與它們產生的結果進行比較。）

``````## At least one conversion needs to be attempted before the
## "integer"-->"numeric" method appears.
as(4L, "numeric")

## (1) Now the methods table shows a new "integer"-->"numeric" specific method
showMethods("coerce")
# Function: coerce (package methods)
# from="ANY", to="array"
#      ... snip ...
# from="ANY", to="numeric"
#      ... snip ...
# from="integer", to="numeric"        ## <-- Here's the new method
#      ... snip ...

## (2) selectMethod now tells a different story
selectMethod("coerce",  signature=c("integer", "numeric"))
# Method Definition:
#
# function (from, to = "numeric", strict = TRUE)
# if (strict) {
#     class(from) <- "numeric"
#     from
# } else from
# <environment: namespace:methods>
#
# Signatures:
#         from      to
# target  "integer" "numeric"
# defined "integer" "numeric"``````

## 我的問題：

1. 為什麼`as(4L, "numeric")`沒有調度到`signature=c("ANY", "numeric")`的可用`coerce()`方法？

2. 如何/為什麼它會在S4方法表中添加新方法？

3. 從哪裡（在R的源代碼或其他地方）， `signature=c("integer", "numeric")``coerce()`方法的定義`signature=c("integer", "numeric")`來了嗎？

`as()`函數的幫助說明：

[...]

[...]

``````if (strict)
asMethod(object)
else asMethod(object, strict = FALSE)``````

``````> myas(4L, 'numeric')
function (from, to = "numeric", strict = TRUE)
if (strict) {
class(from) <- "numeric"
from
} else from
<environment: namespace:methods>
attr(,"target")
An object of class “signature”
from        to
"integer" "numeric"
attr(,"defined")
An object of class “signature”
from        to
"integer" "numeric"
attr(,"generic")
[1] "coerce"
attr(,"generic")attr(,"package")
[1] "methods"
attr(,"class")
[1] "MethodDefinition"
attr(,"class")attr(,"package")
[1] "methods"
attr(,"source")
[1] "function (from, to = \"numeric\", strict = TRUE) "
[2] "if (strict) {"
[3] "    class(from) <- \"numeric\""
[4] "    from"
[5] "} else from"
[1] 4``````

``````> # Snippet 1
> x = 4L
> x = as(x, 'numeric')

> # Snippet 2
> x = 4L
> class(x) <- 'numeric'``````

``````> x = 4
> class(x)
[1] "numeric"
> class(x) <- 'integer'
> class(x)
[1] "integer"``````

``````> x = 4L
> class(x)
[1] "integer"
> is.numeric(x)
[1] TRUE``````

R是一個歷史異常，它的浮點向量有兩個名稱，'double'和'numeric'（之前有'real'）。

'double'是該類型的名稱。 'numeric'是模式的名稱，也是隱式類的名稱。

``````where <- .classEnv(thisClass, mustFind = FALSE)
coerceFun <- getGeneric("coerce", where = where)
coerceMethods <- .getMethodsTable(coerceFun, environment(coerceFun), inherited = TRUE)
asMethod <- .quickCoerceSelect(thisClass, Class, coerceFun, coerceMethods, where)``````

``````function (object, Class, strict = TRUE, ext = possibleExtends(thisClass,
Class))
{
thisClass <- .class1(object)
where <- .classEnv(thisClass, mustFind = FALSE)
coerceFun <- getGeneric("coerce", where = where)
coerceMethods <- .getMethodsTable(coerceFun, environment(coerceFun),
inherited = TRUE)
asMethod <- .quickCoerceSelect(thisClass, Class, coerceFun,
coerceMethods, where)

# No matching signatures from the coerce table!!!
if (is.null(asMethod)) {
sig <- c(from = thisClass, to = Class)
asMethod <- selectMethod("coerce", sig, optional = TRUE,
useInherited = FALSE, fdef = coerceFun, mlist = getMethodsForDispatch(coerceFun))``````

``````        if (is.null(asMethod)) {
canCache <- TRUE
inherited <- FALSE

# The integer vector is numeric!!!
if (is(object, Class)) {
ClassDef <- getClassDef(Class, where)
if (identical(ext, FALSE)) {}
else if (identical(ext, TRUE)) {}
else {
test <- ext@test

# Create S4 coercion method here
asMethod <- .makeAsMethod(ext@coerce, ext@simple,
Class, ClassDef, where)
canCache <- (!is(test, "function")) || identical(body(test),
TRUE)
}
}
if (is.null(asMethod)) {}
else if (canCache)
asMethod <- .asCoerceMethod(asMethod, thisClass,
ClassDef, FALSE, where)
if (is.null(asMethod)) {}
else if (canCache) {
cacheMethod("coerce", sig, asMethod, fdef = coerceFun,
inherited = inherited)
}
}
}

# Use newly created method on object here
if (strict)
asMethod(object)
else asMethod(object, strict = FALSE)``````