在 S4 class 对象中实现基本算术
Implementing basic arithmetic in S4 class object
我正在按以下方式创建 money class 的 S4 对象:
# Create class ------------------------------------------------------------
# Create S4 class object holding money and export to generator function
setClass(Class = "money",
slots = list(currency = "character",
value = "numeric")) -> money
我稍后将为此定义 show 方法:
# Methods -----------------------------------------------------------------
# Create show method
setMethod("show",
"money",
function(object) {
cat(switch(object@currency,
GBP = intToUtf8(163)),
format(
x = round(object@value, 2),
trim = TRUE,
big.mark = ",",
big.interval = 3
),
sep = "")
})
预览
到目前为止它按承诺工作:
# Create test object
tst_fig <- new(Class = "money",
value = 1e6,
currency = "GBP")
# Show the object
tst_fig
# £1,000,000
问题
我想对该对象启用基本算术:
>> tst_fig + 1e6
Error in tst_fig + 1000000 : non-numeric argument to binary operator
想要的结果
> tst_fig + 1e6
# £2,000,000
尝试次数
这自然不行:
>> setMethod("+",
... "money",
... function(object, x) {
... object@value + x
... })
Error in conformMethod(signature, mnames, fnames, f, fdef, definition) :
in method for ‘+’ with signature ‘e1="money"’: formal arguments (e1 = "money", e2 = "money") omitted in the method definition cannot be in the signature
旁注
在 S3 中有类似的 excellent answer provided by @Roland 实现金钱 class;在这个问题的上下文中,我有兴趣创建 S4 class,它会以类似的方式运行,除了好奇之外没有任何特定原因。关键要求是 isS4()
在那个对象上 returns TRUE
.
我的意思类似的方式:
它的打印效果就像格式精美的钱,但允许对普通数字执行的所有操作。
我在自己的问题 here 中遇到了如何做到这一点。我通常使用 setMethod('Arith')
方法,因为当您打算实现多个操作时它更简洁。如果您搜索文档 ?Arith
,您会看到它列出了不同的操作以及其他 S4 组泛型。
正如错误提示,您需要为 Arith
方法定义 e1
和 e2
。在您的具体情况下,以下工作。
注意 - 要获得所需的输出(即 money
class 对象),您需要创建一个新的 money
对象.
setMethod("+",
c(e1="money", e2="numeric"),
function(e1, e2){
new(Class = "money", value = e1@value + e2, currency = e1@currency)
}
)
tst_fig + 1e6
[1] £2e+06
但是,正如我所说,您可能想要更通用、更简洁的版本,它使用 .Generic
来解释您正在使用的 Arith
方法。
setMethod("Arith",
c(e1="money", e2="numeric"),
function(e1, e2)
{
op = .Generic[[1]]
switch(op,
`+` = return(new(Class = "money", value = e1@value + e2, currency = e1@currency))
)
}
)
我正在按以下方式创建 money class 的 S4 对象:
# Create class ------------------------------------------------------------
# Create S4 class object holding money and export to generator function
setClass(Class = "money",
slots = list(currency = "character",
value = "numeric")) -> money
我稍后将为此定义 show 方法:
# Methods -----------------------------------------------------------------
# Create show method
setMethod("show",
"money",
function(object) {
cat(switch(object@currency,
GBP = intToUtf8(163)),
format(
x = round(object@value, 2),
trim = TRUE,
big.mark = ",",
big.interval = 3
),
sep = "")
})
预览
到目前为止它按承诺工作:
# Create test object
tst_fig <- new(Class = "money",
value = 1e6,
currency = "GBP")
# Show the object
tst_fig
# £1,000,000
问题
我想对该对象启用基本算术:
>> tst_fig + 1e6
Error in tst_fig + 1000000 : non-numeric argument to binary operator
想要的结果
> tst_fig + 1e6
# £2,000,000
尝试次数
这自然不行:
>> setMethod("+",
... "money",
... function(object, x) {
... object@value + x
... })
Error in conformMethod(signature, mnames, fnames, f, fdef, definition) :
in method for ‘+’ with signature ‘e1="money"’: formal arguments (e1 = "money", e2 = "money") omitted in the method definition cannot be in the signature
旁注
在 S3 中有类似的 excellent answer provided by @Roland 实现金钱 class;在这个问题的上下文中,我有兴趣创建 S4 class,它会以类似的方式运行,除了好奇之外没有任何特定原因。关键要求是 isS4()
在那个对象上 returns TRUE
.
我的意思类似的方式:
它的打印效果就像格式精美的钱,但允许对普通数字执行的所有操作。
我在自己的问题 here 中遇到了如何做到这一点。我通常使用 setMethod('Arith')
方法,因为当您打算实现多个操作时它更简洁。如果您搜索文档 ?Arith
,您会看到它列出了不同的操作以及其他 S4 组泛型。
正如错误提示,您需要为 Arith
方法定义 e1
和 e2
。在您的具体情况下,以下工作。
注意 - 要获得所需的输出(即 money
class 对象),您需要创建一个新的 money
对象.
setMethod("+",
c(e1="money", e2="numeric"),
function(e1, e2){
new(Class = "money", value = e1@value + e2, currency = e1@currency)
}
)
tst_fig + 1e6
[1] £2e+06
但是,正如我所说,您可能想要更通用、更简洁的版本,它使用 .Generic
来解释您正在使用的 Arith
方法。
setMethod("Arith",
c(e1="money", e2="numeric"),
function(e1, e2)
{
op = .Generic[[1]]
switch(op,
`+` = return(new(Class = "money", value = e1@value + e2, currency = e1@currency))
)
}
)