is.object и система классов S3
С использованием class
Функция позволяет определить класс объекта:
> x = 5
> class(x)
[1] "numeric"
Я также понимаю, что мы можем использовать is.object
команда, чтобы определить, есть ли у объекта класс. Однако некоторые типы объектов являются неявными, то есть
> is.object(x)
[1] FALSE
Было бы правильно заявить, что все переменные в R являются объектами и is.object
такое проверка только для неявных классов?
Кроме того, как типы вписываются в это. Наивно я думал, что следующий фрагмент кода выдаст ошибку:
> x = 5
> class(x) = "fake"
> x = X + 1
> x + 1
[1] 6
attr(,"class")
[1] "fake"
Но x
все еще имеет тип "двойной", все еще все еще работает. Можно ли считать типы суперклассом, от которого наследуются все другие объекты?
2 ответа
typeof
возвращает тип внутреннего представления C, и он не используется для отправки метода. Строго говоря, вы не можете думать о типах как о "суперклассах".
Вместо этого существуют базовые классы (числовые, символьные, списковые, функциональные и т. Д.), Которые примерно соответствуют именам, возвращаемым typeof
, но не всегда (например, тип double имеет числовой класс, special и closure - функцию класса, а класс data.frame - список типов!).
В системах S3 и S4 вы можете создавать нетривиальные классы, используя базовые классы (но не обязательно расширять один из них!! пример: setClass("foo", list(a="numeric",b="character")
не распространяется ни на один из базовых классов).
Для объектов из этих основных классов is.object
возвращается FALSE
, Как говорится в документации, эта функция обеспечивает очень быстрый способ проверить, принадлежит ли объект пользовательскому классу S3 или S4 (т.е. не относится к базовым классам).
После кастинга x
как "фальшивый", ваш объект формально не относится к "числовому" классу:
is(x, "numeric")
#FALSE
но это можно интерпретировать как базовый "числовой" объект:
is.numeric(x)
#TRUE
И вот почему +
работает здесь. Итак, внутренне, как уже сказал @Richie, метод по умолчанию интерпретирует x
по числовому базовому классу.
Этот концептуальный беспорядок из-за неформальной обработки S3 классов. Вместо этого используйте S4.
соответствие между typeof(.) и базовым классом (.):
typeof(.) class(.)
NULL "NULL" "NULL"
1 "double" "numeric"
1:1 "integer" "integer"
1i "complex" "complex"
list(1) "list" "list"
data.frame(x=1) "list" "data.frame"
pairlist(pi) "pairlist" "pairlist"
c "special" "function"
lm "closure" "function"
formals(lm)[[1]] "symbol" "name"
formals(lm)[[2]] "symbol" "name"
y~x "language" "formula"
expression((1))[[1]] "language" "("
(y~x)[[1]] "symbol" "name"
expression(x <- pi)[[1]][[1]] "symbol" "name"
Частичный ответ на первый вопрос находится в Главе 2 определения языка R
R не обеспечивает прямой доступ к памяти компьютера, а предоставляет ряд специализированных структур данных, которые мы будем называть объектами. На эти объекты ссылаются через символы или переменные. Однако в R символы сами являются объектами и ими можно манипулировать так же, как и любым другим объектом.
Итак, да, все переменные являются объектами.
is.object
кажется более или менее эквивалентным function(x) !is.null(attr(x, "class"))
но я готов быть неправым в этом.
Что касается второго вопроса, я думаю, что это то, что происходит: x
имеет класс "подделка", R ищет метод +.fake
кроме того, но когда он не находит, он прибегает к методу по умолчанию. Этот метод по умолчанию основан на базовом коде C, который использует typeof(x)
(или эквивалент C), чтобы определить, что должно быть сделано. В этом случае тип x
это "целое число".