Peng Yu wrote: > On Mon, Oct 26, 2009 at 1:49 PM, Martin Morgan <mtmor...@fhcrc.org> wrote: >> Peng Yu wrote: >>> I thought that 'validity' defined in 'setClass' should be called in >>> 'new'. Could somebody let me know why 'validity' is not called? How to >>> make it be called? >>> >>>> setClass( >>> + Class='A', >>> + representation=representation( >>> + x='numeric' >>> + ), >>> + validity=function(object){ >>> + cat("~~~ A: inspector ~~~\n") >>> + if(obj...@x<0){ >>> + stop("[A:validation] obj...@x<0") >>> + } >>> + return(T) >>> + } >>> + ) >>> [1] "A" >>>> setMethod( >>> + f='initialize', >>> + signature='A', >>> + definition=function(.Object,x){ >>> + cat("~~~ A: initializator ~~~\n") >>> + .obj...@x=x >>> + return(.Object) >>> + } >>> + ) >>> [1] "initialize" >> The default initialize method (initialize,ANY-method) performs simple >> slot assignment and then calls validObject. You do not call the default >> method, so do not get slot assignment or validity checking. If you want >> only to initialize slots as above, then do not write any initialize >> method; let initialize,ANY-method do the work for you. Otherwise, use a >> paradigm like >> >> .Object <- callNextMethod(.Object, x=x, ...) >> >> in your initialize method, so that the slot x is assigned and validity >> checked by the 'next' (eventually, initialize,ANY) method. Note that >> validity is checked in callNextMethod, so that the object has to be >> 'valid' after x has been assigned to it's slot. > > I'm not clear what you mean by 'initialize,ANY-method'. Would you > please give an example based my test case in the original post?
selectMethod(initialize, signature="ANY") is the 'initialize' method applied to an object of class 'ANY' -- initialize,ANY-method (you'll see that this is how methods are documented, with the tag \alias{initialize,A-method} for a method initialize defined on class A). Almost all objects derive from class 'ANY', so this method is the default initialize method. Note that 'new' creates an instance of the class, and then calls initiailize() on that instance. So in a new R session setClass('A', representation=representation(x='numeric')) followed by new('A', x=1) will result in a call to initialize(<instance of A>, x=1). You have not defined an initialize method for the class, so dispatch takes us to initialize,ANY-method, which fills the slots, checks validty, and returns. When you write setMethod(initialize, "A", function(.Object, x, ...) { <code here> }) you've changed the dispatch, and now new("A", x=1) will end up in your method. With setMethod(initialize, "A", function(.Object, x, ...) { callNextMethod(.Object, x=x, ...) }) you call the 'next' method for instances of class 'A', which will eventually be initialize,ANY-method. Don't know if that's any clearer. > >> It is also possible to call validObject explicitly as part of your own >> initialize method. >> >> Two other issues. Calling new("A") with no arguments does NOT call >> validObject, so the default object (e.g., from the prototype argument) >> must be valid a priori. It may be useful to define a constructor A <- >> function(...) new("A", ...) both to provide a nicer interface to the >> user and to map between arguments the user might find convenient and >> slots the class wants to store. > > I also don't quite understand these two issues. Would you please give > me some examples to help me understand them? Thank you! Here's a class that seems never to be valid setClass('A', representation(x='numeric'), validity=function(object) 'not valid') yet > new('A') returns an instance because validity is not called when slots are not assigned by initialize,ANY-method; it is presumed that the author of the class has created a valid object prototype. Maybe it's computationally efficient to store the data in one form, but convenient for the user to provide it in another setClass("A", representation=representation(area="numeric") one could ask that the user call new("A", length=1, width=2) and write an appropriate initialize method, or one could write a constructor A <- function(length=1, width=2, ...) new("A", area=length*width, ...) without an explicit initialize -- let initialize,ANY-method fill the slots. Documenting A provides the user with hints about the arguments and a convenient interface, whereas the signature of 'new' is not helpful. This also removes the developer from having to implement initialize appropriately, which can get complicated. And it provides an abstraction between interface and implementation, again generally a good idea from an oo perspective. This is a matter of programming style, and not an essential component of S4. Martin >> Martin >> >>>> new(Class='A', x=10) >>> ~~~ A: initializator ~~~ >>> An object of class \u201cA\u201d >>> Slot "x": >>> [1] 10 >>> >>> ______________________________________________ >>> R-help@r-project.org mailing list >>> https://stat.ethz.ch/mailman/listinfo/r-help >>> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html >>> and provide commented, minimal, self-contained, reproducible code. >> >> -- >> Martin Morgan >> Computational Biology / Fred Hutchinson Cancer Research Center >> 1100 Fairview Ave. N. >> PO Box 19024 Seattle, WA 98109 >> >> Location: Arnold Building M1 B861 >> Phone: (206) 667-2793 >> > > ______________________________________________ > R-help@r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. -- Martin Morgan Computational Biology / Fred Hutchinson Cancer Research Center 1100 Fairview Ave. N. PO Box 19024 Seattle, WA 98109 Location: Arnold Building M1 B861 Phone: (206) 667-2793 ______________________________________________ R-help@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.