I'm reading Advanced R by Hadley Wickham and I'm confused at section 13.7.3 Group Generics.
I was a bit confused by the phrasing, "...you cannot define your own group generic... defining a single group generic for your class..." but I think this section means to say that if I define the group generic Math.MyClass
then all functions within the Math
group generic (abs
, sign
, etc) will be overwritten for MyClass
objects.
This can be confirmed by running the following:
my_class <- structure(.Data = -1, class = "MyClass")
my_class
# [1] -1
# attr(,"class")
# [1] "MyClass"
abs(my_class)
# [1] 1
# attr(,"class")
# [1] "MyClass"
Math.my_class <- function(x) { x }
abs(my_class)
# [1] -1
# attr(,"class")
# [1] "MyClass"
I understand that this follows the special naming scheme generic.class
but why is the value of .Data
affected in abs(my_class)
?
When I created the variable my_class
, I set the argument .Data = -1
, and the class of -1 is numeric
and that should not have changed:
class(unclass(my_class))
# [1] "numeric"
my_numeric <- unclass(my_class)
class(my_numeric)
# [1] "numeric"
abs(my_numeric)
# [1] 1
So why doesn't abs(my_class)
print the same result (1) before and after I define Math.MyClass
?
I do receive the same results before and after I define Math.MyClass
if I define the group generic as Math.MyClass <- function(x) {NextMethod()}
but what's the point of having group generics then?
And, why do I get the same answer for abs(my_matrix)
both before and after I define Math.matrix
when I run the following:
my_matrix <- matrix(data = -1:-10, ncol = 5) + 0.0
class(my_matrix)
# [1] "matrix"
class(my_matrix[1,1])
# [1] "numeric"
my_matrix
# [,1] [,2] [,3] [,4] [,5]
# [1,] -1 -3 -5 -7 -9
# [2,] -2 -4 -6 -8 -10
abs(my_matrix)
# [,1] [,2] [,3] [,4] [,5]
# [1,] 1 3 5 7 9
# [2,] 2 4 6 8 10
Math.matrix <- function(x) { x }
abs(my_matrix)
# [,1] [,2] [,3] [,4] [,5]
# [1,] 1 3 5 7 9
# [2,] 2 4 6 8 10
And when I run the following:
your_class <- structure(.Data = list(-1), class = "YourClass")
your_class
# [[1]]
# [1] -1
#
# attr(,"class")
# [1] "YourClass"
abs(your_class)
# Error in abs(your_class) : non-numeric argument to mathematical function
class(unclass(your_list))
# [1] "list"
your_list <- list(-1)
class(your_list)
# [1] "list"
abs(your_list)
# Error in abs(your_list) : non-numeric argument to mathematical function
It's clear that the class
of .Data
does matter (initially anyway) because both abs(your_class)
and abs(your_list)
result in the same error.
To make things even more challenging, I found that everything goes back to normal for MyClass
objects once I run rm(Math.MyClass)
:
my_class
# [1] -1
# attr(,"class")
# [1] "MyClass"
abs(my_class)
# [1] -1
# attr(,"class")
# [1] "MyClass"
rm(Math.MyClass)
abs(my_class)
# [1] 1
# attr(,"class")
# [1] "MyClass"
Could someone explain more completely what group generics are (Why do group generics exist / what do they accomplish / what is their parent-child relationship with R objects / why are the data
arguments in some objects affected when the group generic is defined and others are not / etc)?
I have more experience with OOP in Python than in R if you feel it's easier to explain with Python examples. Any help is greatly appreciated!
Aucun commentaire:
Enregistrer un commentaire