将已使用定义的属性添加到R对象可以轻松携带与感兴趣对象粘合在一起的一些其他信息。问题在于它稍微改变了R看到对象的方式,例如具有附加属性的数字向量仍为numeric
,但不再是vector
:
x <- rnorm(100)
class(x)
## [1] "numeric"
is.numeric(x)
## [1] TRUE
is.vector(x)
## [1] TRUE
mode(x)
## [1] "numeric"
typeof(x)
## [1] "double"
attr(x, "foo") <- "this is my attribute"
class(x)
## [1] "numeric"
is.numeric(x)
## [1] TRUE
is.vector(x)
## [1] FALSE # <-- here!
mode(x)
## [1] "numeric"
typeof(x)
## [1] "double"
这会导致任何潜在的问题吗?我想到的是为常见的R对象添加一些属性,然后将它们传递给其他方法。仅仅因为我为标准R对象添加了额外的属性(例如vector,matrix,data.frame等)这一事实会导致某些事情破裂的风险是什么?
注意我不是要求创建自己的类。为简单起见,我们还可以假设在属性名称中没有任何冲突(例如,使用dims
属性)。我们还假设如果某些方法在某些方面会使我的属性失效,那么这不是问题,这是一个可接受的风险。
答案 0 :(得分:12)
在我的(有限的)体验中,向对象添加新属性并没有破坏任何东西。我能想到的唯一可能的情况是,如果一个函数需要一个对象具有一组特定的属性而没有别的东西。我无法想到我遇到过的那段时间。大多数功能,特别是在S3方法中,只会忽略他们不需要的属性。
如果您删除属性,则更有可能出现问题。
您没有看到源自其他属性的许多问题的原因是方法是在对象的class
上调度的。只要课程没有改变,方法将以大致相同的方式发送。但是,这并不意味着现有方法将知道如何处理新属性。采用以下示例 - 向new_attr
和x
添加y
属性,然后添加它们后,结果将采用x
属性。 y
的属性发生了什么变化?默认的+
函数不知道如何处理同名的冲突属性,所以它只需要第一个(更多细节见R Language Definition,谢谢Brodie)。
x <- 1:10
y <- 10:1
attr(x, "new_attr") <- "yippy"
attr(y, "new_attr") <- "ki yay"
x + y
[1] 1 2 3 4 5 6 7 8 9 10
attr(,"new_attr")
[1] "yippy"
在另一个示例中,如果我们为x
和y
属性指定不同的名称,x + y
会生成一个保留两个属性的对象。
x <- 1:10
y <- 10:1
attr(x, "new_attr") <- "yippy"
attr(y, "another_attr") <- "ki yay"
x + y
[1] 11 11 11 11 11 11 11 11 11 11
attr(,"another_attr")
[1] "ki yay"
attr(,"new_attr")
[1] "yippy"
另一方面,mean(x)
甚至没有尝试保留属性。我不知道预测哪些功能将会保留属性的好方法。你可以在基础R中使用一些可靠的助记符(聚合与矢量化,也许是?),但我认为应该考虑一个单独的原则。
如果保留新属性非常重要,则应定义一个保留旧类继承的新类
使用新类,您可以编写扩展泛型的方法,并以您想要的任何方式处理属性。是否应该定义新类并编写其方法在很大程度上取决于您添加的任何新属性对您将要执行的未来工作的价值。
所以一般来说,添加新属性不太可能破坏R中的任何内容。但是如果不添加新的类和方法来处理新属性,我会非常谨慎地解释这些属性之后的含义&#39;已通过其他职能。