答案将取决于你的“数字”如何运作,但我将尝试找出每种方法的优点和缺点,以便你可以做出自己的决定。
class()参数的。因此,如果您有一个类的对象,并且不会调用相同的方法。(更新:显然,该组的成员确实考虑了两个参数的类,因此如果存在or函数,那么在和 的情况下仍然会调用这些函数。但是,对于和 类有单独的方法,使用默认方法,这可能会失败。)xx + 11 + xOps+.myclassOps.myclass1+xx+1x+yxyclass()所有参数的generic.classsetValidity(例如,始终返回 TRUE 的函数以跳过有效性检查)。还要查看组泛型 Ops等Math。即使您需要使用 S4,您也可能只需为这些编写方法即可。(请记住,虽然+和-可以是一元的,也可以是二进制的,但您需要确保该函数在e1是 S4 类 且e2是 的情况下按预期工作missing。根据您的类代表的对象类型,“按预期”可能会意味着抛出错误。)
就效率而言,如果您花费很长时间在方法调度而不是实际计算上,那么您可能做错了什么。特别是,考虑让你的类代表你正在使用的任何类型的数字的向量(如果你确实需要的话,可能是一个列表)。一旦选择了一种方法,无论我们使用 S3 还是 S4,计算都将花费相同的时间,但 S4 将在最后检查对象是否有效。检查通常比方法分派更快,除非类非常复杂(即有很多槽或很深的继承结构)。
如果“效率”只是意味着不编写大量代码,那么组泛型是最好的节省时间的方法。它们适用于 S3 和 S4。
下面是一个组泛型的简单示例。我使用了具有两个槽的类的示例,x作为普通数字和timestamp计算时间。我们希望运营商“对槽进行操作x”,我们通过以下方式实现这一点:
## define simple class based on numeric
timestampedNum <- setClass(
"timestampedNum",
slots=c(timestamp="POSIXct",x="numeric"),
prototype=prototype(timestamp=Sys.time())
)
## set methods for Ops group generic
## we need four of them:
## one for unary +, -
## one for our class [op] something else
## one for something else [op] our class
## one for our class [op] our class
setMethod(
"Ops",
signature = signature(e1="timestampedNum",e2="missing"),
definition = function(e1) timestampedNum(
x=callGeneric(e1@x),
timestamp=Sys.time()
)
)
setMethod(
"Ops",
signature = signature(e1="timestampedNum",e2="ANY"),
definition = function(e1,e2) timestampedNum(
x=callGeneric(e1@x,e2),
timestamp=Sys.time()
)
)
setMethod(
"Ops",
signature = signature(e1="ANY",e2="timestampedNum"),
definition = function(e1,e2) timestampedNum(
x=callGeneric(e1,e2@x),
timestamp=Sys.time()
)
)
setMethod(
"Ops",
signature = signature(e1="timestampedNum",e2="timestampedNum"),
definition = function(e1,e2) timestampedNum(
x=callGeneric(e1@x,e2@x),
timestamp=Sys.time()
)
)
z <- timestampedNum(x=5)
z
+z
-z
z + 1
1 + z
z + z
Run Code Online (Sandbox Code Playgroud)
它生成 6 个类对象timestampedNum,x插槽分别为 5、5、-5、6、6 和 10。
| 归档时间: |
|
| 查看次数: |
104 次 |
| 最近记录: |