I thought classes needed an exportClass directive in NAMESPACE to be exported,
but
Classes defined in a package but not exported are nevertheless exported if there is an initialize method for the class in the code base.
that is to say I can create an instance of the class event though I exported nothing.
so
setClass("example", slots = c( title = "string"))
setClass("example2", slots = c( title = "string"))
and
setMethod("initialize","example, function(.Object, title) {
.Object#title <- title
. Object
})
in the package R directory and NAMESPACE present but with no export directives in it,
results in the possibility to create an instance of the class
library(example_package)
new("example") # ok
new("example2") # fails
I guess this is because initialize is a generics that is already defined
but does it mean you cannot prevent class instantiation by the user of the package if there is an initialize method for the class ?
or maybe put the initialize inside the setClass instruction ?
Related
I've defined a method called "getValues" for a new S4 class in R. My class and method are:
myClass<-setClass("MyClass",
slots=list(a="numeric",b="list"))
setMethod("getValues", signature ( "MyClass", "missing", "missing"),
getValues<-function(x)
{
print("MyClass-getValues called")
})
The 'raster' package already has a method called 'getValues' but with different signatures (can be seen with showMethods("getValues")). So I thought method dispatching will select the correct method depending of the signature. But when I run:
a<-raster()
getValues(a) #problem: this calls "getValues" of the class 'MyClass' and prints "MyClass-getValues called"
I expected that the 'getValues' method for RasterLayer objects will be called, but this calls "getValues" of the class 'MyClass'!
Where is the error?
The error is in the commented line below:
myClass<-setClass("MyClass",
slots=list(a="numeric",b="list"))
setMethod("getValues", signature ( "MyClass", "missing", "missing"),
##getValues<-function(x)##
{
print("MyClass-getValues called")
})
This line overwrites the main definition of getValues as well as setting a method. Call this function anything other than getValues and it should work.
Suppose I have two packages PackageA and PackageB. I have an S4 class, ClassA, in PackageA that I would like to use as a base class for ClassB in PackageB:
setClass(
"ClassB",
slots = c(),
validity = function(object) {
T
}
contains = "ClassA")
However, when I build I get the error:
no definition found for superclass "ClassA"
I have tried adding a reference to the PackageA with devtools:
devtools::use_package("PackageA")
Perhaps I need to use an roxygen directive?
Turns out that ClassA was not being imported properly. Adding the correct roxygen directive solved the problem:
#' #import PackageA
setClass(
"ClassB",
slots = c(),
validity = function(object) {
T
}
contains = "ClassA")
I am having problem with getting the class names of all classes which are inherited from a base class.
Class Base
{
};
Class A:public Base
{
};
Class B:public Base
{
};
Class C:public Base
{
};
.....so on. My requirement is that I want to know all the class names which are inherited from class Base. Is there any way or method from base class that I can know all the classes? Thanks in advance.
Qt allows to do this with the following limitations:
All involved classes should be derived from QObject.
Each class should be registered in a global class list. Qt doesn't provide a way to get full list of classes.
Meta information about a QObject-derived class is stored in a QMetaObject that can be accessed via T::staticMetaObject. First of all, you want to have a list of all metaobjects in your application. You can use something like this:
QList<const QMetaObject*> global_list;
template<class T> register_class() {
global_list << &T::staticMetaObject;
}
//execute the following at program initialization
register_class<Base>();
register_class<A>();
register_class<B>();
register_class<C>();
To get list of class names derived from Base, you need to:
Get const QMetaObject* of the target class as &Base::staticMetaObject.
Iterate over global list of metaobjects and check if QMetaObject::superClass returns target meta object. You may need to perform recursive check if indirect inheritance should also be detected.
Get names of found subclasses with QMetaObject::className.
I have an R6 class and I want to add an S3 method for it. The documentation I found mentioned briefly that in order to use S3 dispatch on R6 you must have class = TRUE, but I couldn't find an example of how it should be done.
I did see empirically that simply writing an S3 method in the form s3generic.r6class worked, but I wanted to know if that is indeed to right way to write an S3 method for R6.
For example, say I have an R6 class that enhances a list
library(R6)
R6list <- R6Class(
"R6list",
public = list(
orig = NULL,
initialize = function(x) {
self$orig <- x
}
)
)
Question 1
Naturally, I want to provide a method for obtaining the underlying list, so I wanted to add an as.list method. Is it standard to add both an S3 generic AND a as.list public function inside the class? My intuitive answer is to add both.
R6list <- R6Class(
"R6list",
public = list(
orig = NULL,
initialize = function(x) {
self$orig <- x
},
as.list = function() {
self$orig
}
)
)
as.list.R6list <- function(x, ...) {
x$as.list()
}
So that now if I have an object mylist <- R6list$new(as.list(letters[1:5])) I can either call as.list(mylist) or mylist$as.list(). Is one of those preferred over the other?
Question 2
Is there anything special about writing an S3 method for R6 classes, or is what I wrote above sufficient and the correct way? I wasn't sure if the S3 method has to be written outside of the class definition, or if R6 somehow provides a way to write S3 methods within it so that all the code relating to the class is localized.
I asked Winston Chang, the author of R6, about this on Github. According to him, the code provided in Question 1 above is the correct way of writing S3 methods for R6 classes.
I am trying to override a reference class method. Because reference class methods are bound to the class rather than the object, I believe in order to do this I need to define a new reference class which inherits from the old reference class. However the class I am trying to inherit from is defined in an external package to mine (dplyr). I cannot figure out the correct syntax to do this, contains seems to require only a text name, and does not search for class definitions in external packages.
In particular I am trying to inherit from the DbDisconnector reference class from dplyr and override the finalize method.
This correctly finds the parent class, but then cannot assign to it as it is from a different package.
NewDbDisconnector <- setRefClass("NewDbDisconnector",
contains = 'DbDisconnector',
methods = list(
finalize = function() {
message("test")
}
),
where=getNamespace('dplyr')
)
# Error in assign(mname, def, where) (from file.r#75) :
# cannot add bindings to a locked environment
Contains methods only accept strings, they cannot just be given a refClass definition from getRefClass.
NewDbDisconnector <- setRefClass("NewDbDisconnector",
contains = getRefClass("DbDisconnector", getNamespace("dplyr")),
methods = list(
finalize = function() {
message("test")
}
)
)
# Error in FUN(X[[1L]], ...) :
# the 'contains' argument should be the names of superclasses: got an element of class “name”
I would think this should be possible, I just cannot figure out the correct way to do it.
You can import the superclass to your environment:
DbDisconnector <- getFromNamespace("DbDisconnector", "dplyr")
And then set contains = "DbDisconnector" in your class.