From cstrato at aon.at  Fri Apr  6 21:37:53 2007
From: cstrato at aon.at (cstrato)
Date: Fri, 06 Apr 2007 21:37:53 +0200
Subject: [Rd] Problem with S4 inheritance: unexpected re-initialization?
In-Reply-To: <46168B16.4090703@fhcrc.org>
References: <46112187.3090009@aon.at>
	<4612CCAB.1080809@fhcrc.org>	<4613BE1D.5000507@aon.at>
	<4613F186.1060507@fhcrc.org>	<46152B35.2070200@aon.at>
	<6phfy7dlw4p.fsf@gopher4.fhcrc.org> <46168B16.4090703@fhcrc.org>
Message-ID: <4616A191.2070109@aon.at>

Dear Herve

Although I am currently learning to use S4 classes, and thus I am 
probably not the person
to comment on S4 classes, I completely agree with you.

Coming from C++ (most of my code is C++), this is what I have 
intuitively expected,
although I was not able to formulate it. I am glad that you did.

At the moment I try to find out if there is a possibility to circumvent 
this problem.
I do not know if there is a possibility to set an object to NULL 
initially, and then
call: "if (!is.null(object)) do something"

Best regards
Christian



Herve Pages wrote:
> Martin,
>
> Martin Morgan wrote:
>   
>> The funny effect where class(object) seems to trigger construction of
>> a new object is lazy evaluation -- the 'object' argument to
>> setValidity is not evaluated until needed, i.e., until class(object)
>> (anything would trigger this, including force(object)); only then do
>> you see the attempt to create the new object of the previous
>> paragraph.
>>     
>
> The fact that you can't predict the number of times the "initialize"
> method will be called is problematic. Here is a simple example
> where "initialize-A" increments a global counter to keep track of the
> number of A-objects:
>
>   A.GLOBALS <- new.env(parent=emptyenv())
>   A.GLOBALS[["nobjs"]] <- 0L
>
>   setClass("A",
>     representation(a="character"),
>     prototype(a="a0")
>   )
>   setMethod("initialize", "A",
>     function(.Object, ...) {
>         cat("------initialize:A------\n")
>         A.GLOBALS[["nobjs"]] <- A.GLOBALS[["nobjs"]] + 1
>         cat("A-object #", A.GLOBALS[["nobjs"]], "\n", sep="")
>         callNextMethod()
>     }
>   )
>   setValidity("A",
>     function(object) {
>         cat("------setValidity:A------\n")
>         tmp <- class(object)
>         TRUE
>     }
>   )
>
>   setClass("B",
>     contains="A",
>     representation(b = "character")
>   )
>   setMethod("initialize", "B",
>     function(.Object, ...) {
>         cat("------initialize:B------\n")
>         callNextMethod()
>     }
>   )
>   setValidity("B",
>     function(object) {
>         cat("------setValidity:B------\n")
>         TRUE
>     }
>   )
>
> Let's try it:
>
>   > b1 <- new("B")
>   ------initialize:B------
>   ------initialize:A------
>   A-object #1
>   > A.GLOBALS[["nobjs"]]
>   [1] 1
>
>   > b1 <- new("B", b="hello")
>   ------initialize:B------
>   ------initialize:A------
>   A-object #2
>   ------setValidity:A------
>   ------initialize:A------
>   A-object #3
>   ------setValidity:B------
>   > A.GLOBALS[["nobjs"]]
>   [1] 3
>
> Shouldn't the "initializing" ("constructor" in other languages) code be executed
> exactly 1 time per object instanciation? Something that the programmer can simply
> rely on, whatever this code contains and whatever the internal subtilities of the
> programming lamguage are?
>
> Cheers,
> H.
>
>
>
>



[Rd] Problem with S4 inheritance: unexpected re-initialization?
cstrato