El funcionamiento interno de `NextMethod()`
oop inheritance (2)
Considere este ejemplo donde se llama a la función genérica f
e invoca f.ordered
y luego, utilizando NextMethod
, f.ordered
invoca f.factor
:
> f <- function(x) UseMethod("f") # generic
> f.ordered <- function(x) { x <- x[-1]; NextMethod() }
> f.factor <- function(x) x # inherited method
> x <- ordered(c("a", "b", "c"))
> class(x)
[1] "ordered" "factor"
> f(x)
[1] b c
Levels: a < b < c
Ahora considere el texto original:
Pasando ahora a los métodos invocados como resultado de una llamada a NextMethod (), estos se comportan como si hubieran sido invocados desde el método anterior con una llamada especial.
Aquí f
llama a f.ordered
que llama a f.factor
por lo que el método "invocado como resultado de una llamada a NextMethod" es f.factor
y el método anterior es f.ordered
.
Los argumentos en la llamada al método heredado son los mismos en número, orden y nombres de argumento reales que en la llamada al método actual (y, por lo tanto, en la llamada al genérico). Las expresiones para los argumentos, sin embargo, son los nombres de los argumentos formales correspondientes del método actual. Supongamos, por ejemplo, que la expresión print (calificaciones) ha invocado el método print.ordered (). Cuando este método invoca a NextMethod (), esto es equivalente a una llamada a print.factor () del formulario print.factor (x), donde x es aquí la x en el marco de print.ordered ()
Ahora cambiamos las perspectivas y estamos sentados en f.ordered
lo tanto, ahora el método actual es f.factor
y el método f.factor
es el método heredado.
En el punto en que f.ordered
invoca a NextMethod()
se construye una llamada especial para llamar a f.factor
cuyos argumentos son los mismos que aquellos pasados a f.ordered
y al f
genérico, excepto que se refieren a las versiones de los argumentos en f.ordered
(que hace una diferencia aquí cuando f.ordered
cambia el argumento antes de invocar f.factor
.
Estoy intentando descubrir cómo funciona NextMethod()
. La explicación más detallada que he encontrado del sistema de clase S3 está en Chambers & Hastie (edts.) Modelos estadísticos en S (1993, Chapman & Hall), sin embargo, creo que la parte relativa a la invocación de NextMethod
un poco oscura. Los siguientes son los párrafos relevantes que trato de encontrarle sentido (pp. 268-269).
Pasando ahora a los métodos invocados como resultado de una llamada a
NextMethod()
, estos se comportan como si hubieran sido invocados desde el método anterior con una llamada especial. Los argumentos en la llamada al método heredado son los mismos en número, orden y nombres de argumento reales que en la llamada al método actual (y, por lo tanto, en la llamada al genérico). Las expresiones para los argumentos, sin embargo, son los nombres de los argumentos formales correspondientes del método actual. Supongamos, por ejemplo, que la expresiónprint(ratings)
ha invocado el métodoprint.ordered()
. Cuando este método invoca aNextMethod()
, esto es equivalente a una llamada aprint.factor()
del formularioprint.factor(x)
, dondex
es aquí lax
en el marco deprint.ordered()
. Si varios argumentos coinciden con el argumento formal "...
", esos argumentos se representan en la llamada al método heredado y los nombres especiales "..1
", "..2
", etc. El evaluador reconoce estos nombres y los trata de manera apropiada (ver página 476 para un ejemplo).Esta definición bastante sutil existe para asegurar que la semántica de las llamadas a funciones en S se traslade tan limpiamente como sea posible al uso de métodos (compárese con el nuevo lenguaje de Becker, Chambers y Wilks, página 354). En particular:
- Los argumentos se transmiten desde el método actual al método heredado con sus valores actuales en el momento en que se llama a
NextMethod()
.- La evaluación diferida continúa en efecto; los argumentos no evaluados permanecen sin evaluar.
- Faltan argumentos faltantes en el método heredado.
- Los argumentos transmitidos a través del argumento formal "
...
" llegan con el nombre del argumento correcto.- Los objetos en el marco que no se corresponden con los argumentos reales en la llamada no se pasarán al método heredado ".
El proceso de herencia es esencialmente transparente en lo que respecta a los argumentos.
Dos puntos que encuentro confusos son:
- ¿Qué es "el método actual" y cuál es "el método anterior"?
- ¿Cuál es la diferencia entre "Los argumentos en la llamada al método heredado", "Las expresiones para los argumentos" y "Los nombres de los argumentos formales correspondientes del método actual"?
En términos generales, si alguien pudiera repetir la descripción dada en los párrafos anteriores de una manera lucifer, lo agradecería.
Es difícil revisar toda esta publicación, pero creo que este pequeño ejemplo puede ayudar a desconcertar el envío del siguiente método.
Creo un objeto con 2 atributos de clases (herencia) ''primero'' y ''segundo''.
x <- 1
attr(x,''class'') <- c(''first'',''second'')
Luego creo un método generic
Cat
para imprimir mi objeto
Cate <- function(x,...)UseMethod(''Cate'')
Cate
método de Cate
para cada clase.
Cate.first <- function(x,...){
print(match.call())
print(paste(''first:'',x))
print(''---------------------'')
NextMethod() ## This will call Cate.second
}
Cate.second <- function(x,y){
print(match.call())
print(paste(''second:'',x,y))
}
Ahora puede verificar la llamada de Cate
usando este ejemplo:
Cate(x,1:3)
Cate.first(x = x, 1:3)
[1] "first: 1"
[1] "---------------------"
Cate.second(x = x, y = 1:3)
[1] "second: 1 1" "second: 1 2" "second: 1 3"
- Para Cate.second, el método anterior es Cate.first
- Los argumentos xey se transmiten desde el método actual al método heredado con sus valores actuales en el momento en que se llama a NextMethod ().
- El argumento y pasado a través del argumento formal "..." llega con el nombre de argumento correcto
Cate.second(x = x, y = 1:3)