Dear All....I am really struggling with oo in R. Trying to set attributes of the base class in a derived class method but the slot is only populated in the method itself, not when I try to print out the object from the console. Code is library(RODBC) # # ----------------------------------------------------- # Define a medical event class. This is abstract (VIRTUAL) # ----------------------------------------------------- # setClass("Medical_Event", representation( Event_Name="character", Capacity_Profile="numeric", Delay_Profile="numeric", "VIRTUAL"), prototype(Event_Name="An Event",Capacity_Profile=c(.2,.2,.2,.2,.2,0,0))) setGeneric("getDelayProfile",function(object){standardGeneric("getDelayProfile")},simpleInheritanceOnly=T) # ------------------------------------------ # Now define a derived class called GP_Event # ------------------------------------------ setClass("GP_Event",representation(Surgery_Name="character"),contains=c("Medical_Event"),prototype(Surgery_Name="Unknown")) # ----------------------------------------- # Now define a derived class called OP_Appt # ----------------------------------------- setClass("OP_Appt",representation(Clinic_Name="character"),contains=c("Medical_Event"),prototype(Clinic_Name="Unknown")) setMethod(f="getDelayProfile",signature("OP_Appt"),definition=function(object) { OpTablesDB<-odbcDriverConnect("DRIVER=Microsoft Access Driver (*.mdb, *.accdb); DBQ=Z:\\srp\\Development Code\\Projects\\CancerPathwaySimulation\\Database\\CancerPathway.accdb") strQuery<-"select * from op_profile" odbcQuery(OpTablesDB,strQuery) dfQuery<-odbcFetchRows(OpTablesDB) odbcClose(OpTablesDB) delay<-dfQuery$data[[1]][1:70] prob<-dfQuery$data[[2]][1:70] # as(object,"Medical_Event")@Delay_Profile<-prob object at Delay_Profile <- prob object } ) if I instantiate a new instance of the derived class *aTest<-new("OPP_Appt")*and then try and populate the attribute Delay_Profile by *getDelayProfile(aTest) * the object slot seems to be populated in the method because I can print it out, viz An object of class "OP_Appt" Slot "Clinic_Name": [1] "Unknown" Slot "Event_Name": [1] "An Event" Slot "Capacity_Profile": [1] 0.2 0.2 0.2 0.2 0.2 0.0 0.0 *Slot "Delay_Profile": [1] 14 21 25 29 27 49 72 71 43 65 102 134 223 358 24 14 21 25 35 31 38 43 31 23 21 26 46 54 42 26 [31] 34 24 25 41 48 33 30 17 18 31 24 35 35 24 16 32 36 39 46 36 26 16 27 21 30 32 33 27 7 5 [61] 9 10 9 11 8 6 1 11 14 10* but when the method returns and I type *aTest* I get An object of class "OP_Appt" Slot "Clinic_Name": [1] "Unknown" Slot "Event_Name": [1] "An Event" Slot "Capacity_Profile": [1] 0.2 0.2 0.2 0.2 0.2 0.0 0.0 *Slot "Delay_Profile": numeric(0)* ie the Delay_Profile slot is empty???? What haven't I done - can anybody help me please? Many Thanks Steve Creamer -- View this message in context: http://r.789695.n4.nabble.com/Setting-Derived-Class-Slots-tp4671683.html Sent from the R help mailing list archive at Nabble.com.
On 07/16/2013 06:36 AM, Steve Creamer wrote:> Dear All....I am really struggling with oo in R. Trying to set attributes of > the base class in a derived class method but the slot is only populated in > the method itself, not when I try to print out the object from the console. > > Code is > > library(RODBC) > # > # ----------------------------------------------------- > # Define a medical event class. This is abstract (VIRTUAL) > # ----------------------------------------------------- > # > setClass("Medical_Event", > representation( > Event_Name="character", > Capacity_Profile="numeric", > Delay_Profile="numeric", > "VIRTUAL"), > prototype(Event_Name="An > Event",Capacity_Profile=c(.2,.2,.2,.2,.2,0,0))) > > setGeneric("getDelayProfile",function(object){standardGeneric("getDelayProfile")},simpleInheritanceOnly=T) > > # ------------------------------------------ > # Now define a derived class called GP_Event > # ------------------------------------------ > > setClass("GP_Event",representation(Surgery_Name="character"),contains=c("Medical_Event"),prototype(Surgery_Name="Unknown")) > > # ----------------------------------------- > # Now define a derived class called OP_Appt > # ----------------------------------------- > > setClass("OP_Appt",representation(Clinic_Name="character"),contains=c("Medical_Event"),prototype(Clinic_Name="Unknown")) > > > setMethod(f="getDelayProfile",signature("OP_Appt"),definition=function(object) > { > OpTablesDB<-odbcDriverConnect("DRIVER=Microsoft Access Driver (*.mdb, > *.accdb); > DBQ=Z:\\srp\\Development > Code\\Projects\\CancerPathwaySimulation\\Database\\CancerPathway.accdb") > strQuery<-"select * from op_profile" > odbcQuery(OpTablesDB,strQuery) > dfQuery<-odbcFetchRows(OpTablesDB) > odbcClose(OpTablesDB) > delay<-dfQuery$data[[1]][1:70] > prob<-dfQuery$data[[2]][1:70] > # as(object,"Medical_Event")@Delay_Profile<-prob > object at Delay_Profile <- prob > object > } > ) > > if I instantiate a new instance of the derived class > > *aTest<-new("OPP_Appt")*and then try and populate the attribute > Delay_Profile by > > *getDelayProfile(aTest) * > > the object slot seems to be populated in the method because I can print it > out, viz > > An object of class "OP_Appt" > Slot "Clinic_Name": > [1] "Unknown" > > Slot "Event_Name": > [1] "An Event" > > Slot "Capacity_Profile": > [1] 0.2 0.2 0.2 0.2 0.2 0.0 0.0 > > *Slot "Delay_Profile": > [1] 14 21 25 29 27 49 72 71 43 65 102 134 223 358 24 14 21 25 > 35 31 38 43 31 23 21 26 46 54 42 26 > [31] 34 24 25 41 48 33 30 17 18 31 24 35 35 24 16 32 36 39 > 46 36 26 16 27 21 30 32 33 27 7 5 > [61] 9 10 9 11 8 6 1 11 14 10* > > but when the method returns and I type > > *aTest* > > I get > > An object of class "OP_Appt" > Slot "Clinic_Name": > [1] "Unknown" > > Slot "Event_Name": > [1] "An Event" > > Slot "Capacity_Profile": > [1] 0.2 0.2 0.2 0.2 0.2 0.0 0.0 > > *Slot "Delay_Profile": > numeric(0)* > > ie the Delay_Profile slot is empty???? > > What haven't I done - can anybody help me please?It helps to provide a more minimal example, preferably reproducible (no data base queries needed to illustrate your problem); I'm guessing that, just as with f = funtion(l) { l$a = 1; l } lst = list(a=0, b=1) one would 'update' lst with lst = f(lst) and not f(lst) you need to assign the return value to the original object aTest <- getDelayProfile(aTest) Martin> Many Thanks > > Steve Creamer > > > > > -- > View this message in context: http://r.789695.n4.nabble.com/Setting-Derived-Class-Slots-tp4671683.html > Sent from the R help mailing list archive at Nabble.com. > > ______________________________________________ > R-help at 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. >-- 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
Hi Steve, it seems to me, that you want to pass an object inside of getDelayProfile. In this case you must use setReplaceMethod("getDelayProfile<-",....) in your definition inside the virtual and of course also in the specification of OP_Appt. R does not know, that your function should give back an object, that replaces the one on which it was called. Otherwise making any modifications on the slot of the object inside the function will never arrive at the object outside of the function. They have two different environments and as soon as you modify an object inside of a function R builds a copy of it. See more about this by googling R pass-by-value. By the way: I wouldn't call this function getDelayProfile as getters and setters have usually differing a different meaning (encapsulation) in OO programming. Use rather something like fetchDelayProfile or initializeDelayProfile. It will probably make it easier for Users and Programmers to work with your program. Hope this helps Best Simon On Jul 16, 2013, at 3:36 PM, Steve Creamer <stephen.creamer@nhs.net> wrote:>[[alternative HTML version deleted]]