Hi, I am trying to understand S3 classes. I have read several tutorials about the topics but I am still a bit confused. I guess it is because it is so different from Java OOP. I have pasted my attempt at creating a bank-account class below and my problems are: 1. What should be added some plot.default() calls the account$plot() method ? 2. What should the account$plot() be implemented to show some kind of plot ? 3. How can one function inside "me"-list called another function. Eg. How can account$plot() call account$pastSaldo() ? Here are my code. Feel free to comment on any aspect of the code. ps. I hope I have manage to strip HTML. Regards Martin account <- function(owner = NULL) { thisEnv <- environment() pastSaldo <- vector() saldo <- 0 owner <- owner me <- list( thisEnv = thisEnv, getEnv = function() { return(get("thisEnv", thisEnv)) }, balance = function() { return(get("saldo", thisEnv)) }, deposit = function(value) { assign("pastSaldo", append(pastSaldo, saldo), thisEnv) assign("saldo", saldo + value, thisEnv) }, withdraw = function(value) { assign("pastSaldo", append(pastSaldo, saldo), thisEnv) assign("saldo", saldo - value, thisEnv) }, pastSaldo = function() { return(pastSaldo) }, plot = function() { plot.new() lines(list(y = pastSaldo, x = seq_along(pastSaldo))) } ) assign('this', me, envir = thisEnv) class(me) <- append(class(me), "account") return(me) } FirstAccount <- account("Martin") FirstAccount$deposit(100) FirstAccount$withdraw(50) FirstAccount$deposit(200) FirstAccount$balance() FirstAccount$pastSaldo() FirstAccount$plot() plot(FirstAccount) # fails plot.account(FirstAccount) # fails
On 02/01/2018 6:38 PM, Martin M?ller Skarbiniks Pedersen wrote:> Hi, > > I am trying to understand S3 classes. I have read several tutorials about > the topics but I am still a bit confused. I guess it is because it is > so different from > Java OOP.What you do below isn't S3. S3 is a system where the classes are secondary to the generic functions. Methods "belong" to generics, they don't belong to classes. As far as I can see, you hardly make use of S3 methods and generics at all. For the style you're using, the R6 or R.oo packages might be more suitable.> > I have pasted my attempt at creating a bank-account class below and > my problems are: > > 1. What should be added some plot.default() calls the account$plot() method ?No, you need to define a function called "plot.account" whose signature is compatible with plot, i.e. arguments (x, y, ...), possibly with extra parameters as well. It should do the plotting.> 2. What should the account$plot() be implemented to show some kind of plot ?The plot.account function could call account$plot(); it can do whatever you want to plot the object.> 3. How can one function inside "me"-list called another function. Eg. > How can account$plot() call account$pastSaldo() ?There's no particular support for having them see each other the way you've defined them. A better way to define them would be as local functions within the account body; then they'd be able to see each other without any prefix. Duncan Murdoch> > Here are my code. Feel free to comment on any aspect of the code. > ps. I hope I have manage to strip HTML. > > Regards > Martin > > > > account <- function(owner = NULL) { > thisEnv <- environment() > > pastSaldo <- vector() > saldo <- 0 > owner <- owner > > me <- list( > thisEnv = thisEnv, > > getEnv = function() { return(get("thisEnv", thisEnv)) }, > > balance = function() { return(get("saldo", thisEnv)) }, > > deposit = function(value) { > assign("pastSaldo", append(pastSaldo, saldo), thisEnv) > assign("saldo", saldo + value, thisEnv) > }, > > withdraw = function(value) { > assign("pastSaldo", append(pastSaldo, saldo), thisEnv) > assign("saldo", saldo - value, thisEnv) > }, > > pastSaldo = function() { > return(pastSaldo) > }, > > plot = function() { > plot.new() > lines(list(y = pastSaldo, x = seq_along(pastSaldo))) > } > ) > assign('this', me, envir = thisEnv) > > class(me) <- append(class(me), "account") > return(me) > } > > FirstAccount <- account("Martin") > FirstAccount$deposit(100) > FirstAccount$withdraw(50) > FirstAccount$deposit(200) > FirstAccount$balance() > FirstAccount$pastSaldo() > > FirstAccount$plot() > > plot(FirstAccount) # fails > plot.account(FirstAccount) # fails > > ______________________________________________ > R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see > 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. >
On 3 January 2018 at 00:52, Duncan Murdoch <murdoch.duncan at gmail.com> wrote:> On 02/01/2018 6:38 PM, Martin M?ller Skarbiniks Pedersen wrote: >> >> Hi, >> >> I am trying to understand S3 classes. I have read several tutorials >> about >> the topics but I am still a bit confused. I guess it is because it is >> so different from >> Java OOP. > > > What you do below isn't S3. S3 is a system where the classes are secondary > to the generic functions. Methods "belong" to generics, they don't belong > to classes. As far as I can see, you hardly make use of S3 methods and > generics at all. > > For the style you're using, the R6 or R.oo packages might be more suitable.OK. Thanks, I will rewrite the code. I read the guide at https://www.programiz.com/r-programming/S3-class to make the code. And used the part under: 1.3.2. Local Environment Approach There is a picture of Wickham and it is sponsored by Datacamp so I was thinking it was a good place for a guide ?! Regards Martin
On 3 January 2018 at 00:52, Duncan Murdoch <murdoch.duncan at gmail.com> wrote:> On 02/01/2018 6:38 PM, Martin M?ller Skarbiniks Pedersen wrote: >> >> Hi, >> >> I am trying to understand S3 classes. I have read several tutorials >> about >> the topics but I am still a bit confused. I guess it is because it is >> so different from >> Java OOP. > > > What you do below isn't S3. S3 is a system where the classes are secondary > to the generic functions. Methods "belong" to generics, they don't belong > to classes. As far as I can see, you hardly make use of S3 methods and > generics at all.Here is my second attempt making a S3-class. But something is wrong with the deposit.account() ? Thanks for any help. I expect this output: [1] 0 Martin Saldo is: 100 but I get this: [1] 100 Martin Saldo is: 0 Regards Martin account <- function(owner = NULL) { if (is.null(owner)) stop("Owner can't be NULL") value <- list(owner = owner, saldo = 0) attr(value, "class") <- "account" value } balance <- function(obj) { UseMethod("balance") } balance.account <- function(obj) { obj$saldo } deposit <- function(obj, amount) { UseMethod("deposit") } deposit.account <- function(obj, amount) { obj$saldo <- obj$saldo + amount } print.account <- function(obj) { cat(obj$owner, "\n") cat("Saldo is: ", obj$saldo, "\n") } A1 <- account("Martin") deposit(A1, 100) balance(A1) print(A1)