R语言 S3类
R语言中的所有事物都被认为是对象。对象有属性,与对象相关的最常见的属性是类。命令class用于定义一个对象的类或了解一个对象的类。
Class是一个向量,这个属性允许两件事:
- 允许对象从众多的类中继承
- 可以为复杂的类指定继承的顺序
例子。检查一个对象的类
# Creating a vector x consisting of type of genders
x<-c("female", "male", "male", "female")
# Using the command <code>class()</code>
# to check the class of the vector
class(x)
输出:
[1] "character"
例子。添加一个对象的类别
# Creating a vector x consisting of type of genders
x<-c("female", "male", "male", "female")
# Using the command <code>class()</code>
# to append the class of the vector
class(x)<-append(class(x), "Gender")
class(x)
输出:
[1] "character" "Gender"
管理内存
在进行面向对象的编程时,程序员可能会对使用哪个类产生疑问–S3还是S4?
当比较这两个类时,S4有一个更结构化的方法,而S3被认为是一个灵活的类。
内存环境负责S3类的灵活性。
一个环境就像一个局部范围,有一个与它相关的变量集。如果知道与环境相关的 “ID”,就可以访问这些变量。
为了知道或设置环境中的变量值,可以使用 assign 和 get 等命令。
例子。在环境中分配和获取变量的值
# Creating a vector x consisting of type of genders
# Creating a vector for age
age<-c(12, 10, 09)
# The command environment() can be used
# to bring the pointer to current environment
e <- environment()
e
# Setting the value of the variable
assign("age", 3, e)
ls()
# Getting the values of the variable
get("age", e)
输出:
[1] "age" "e" "x"
[1] 3
环境可以很容易地被创建。它们也可以被嵌入到其他环境中。
创建一个S3类
S3类是R编程中最普遍和最常用的类。实现这个类很容易,大多数预定义的类都是这种类型的。
一个S3对象基本上是一个列表,它的类属性被分配了一些名字。而创建对象的成员变量是列表的组成部分。
对于创建S3对象,有两个主要步骤:
- 创建一个带有所需组件的列表(比如x)。
- 然后通过命令class(x)形成一个类,并为这个类指定一个名字。
例子。可以很容易地创建一个银行账户细节的S3对象。
x <- list(name ="Arjun", account_no = 1234,
saving = 1500, withdrawn = 234)
class(x)<-"bank"
x
**输出:**
name
[1] "Arjun"account_no
[1] 1234
saving
[1] 1500withdrawn
[1] 234
attr(, "class")
[1] "bank"
例子。可以很容易地创建一个人的简历的S3对象
x <- list(name ="Arjun", percentage = 95,
school_name ="ST Xavier")
class(x)<-"resume"
x
输出:
$name
[1] "Arjun"
$percentage
[1] 95
$school_name
[1] "ST Xavier"
attr(, "class")
[1] "resume"
其他语言如Python、Java、C++等对类有适当的定义,对象有适当的定义方法和属性。
,但在R语言的S3类系统中,它是灵活的,你甚至可以修改或转换它们(同一类的对象可以不同)。
R语言的S3系统包括三个主要部分
- 通用函数
- 方法
- 属性
通用函数
R语言非常频繁地使用print()函数。如果你输入类的名称,它的内部结构将被打印出来,或者你可以使用print(类的名称)命令。但是同样的函数print()被用来打印不同的东西,比如–向量、数据框、矩阵等等。
print()是如何识别这些不同的输入的
函数print()是一个通用函数,因此是一个方法的集合。这些方法可以通过输入methods(print)命令进一步检查。
methods(print)
输出:
[1] print.AES*
[2] print.Arima*
[3] print.AsIs
[4] print.Bibtex*
[5] print.CRAN_package_reverse_dependencies_and_views*
[6] print.DLLInfo
[7] print.DLLInfoList
[8] print.DLLRegisteredRoutines
[9] print.Date
[10] print.Dlist
[11] print.HoltWinters*
[12] print.LaTeX*
[13] print.Latex*
[14] print.MethodsFunction*
[15] print.NativeRoutineList
[16] print.PDF_Array*
[17] print.PDF_Dictionary*
[18] print.PDF_Indirect_Reference*
[19] print.PDF_Keyword*
[20] print.PDF_Name*
[21] print.PDF_Stream*
[22] print.PDF_String*
[23] print.POSIXct
[24] print.POSIXlt
[25] print.R6*
[26] print.R6ClassGenerator*
[27] print.RGBcolorConverter*
[28] print.Rcpp_stack_trace*
[29] print.Rd*
[30] print.SOCK0node*
[31] print.SOCKcluster*
[32] print.SOCKnode*
[33] print.State*
[34] print.StructTS*
[35] print.TukeyHSD*
[36] print.acf*
[37] print.anova*
[38] print.aov*
[39] print.aovlist*
[40] print.ar*
[41] print.arima0*
[42] print.aspell*
[43] print.aspell_inspect_context*
[44] print.bibentry*
[45] print.browseVignettes*
[46] print.by
[47] print.bytes*
[48] print.changedFiles*
[49] print.checkDocFiles*
[50] print.checkDocStyle*
[51] print.checkFF*
[52] print.checkRd*
[53] print.checkReplaceFuns*
[54] print.checkS3methods*
[55] print.checkTnF*
[56] print.checkVignettes*
[57] print.check_Rd_contents*
[58] print.check_Rd_line_widths*
[59] print.check_Rd_metadata*
[60] print.check_Rd_xrefs*
[61] print.check_RegSym_calls*
[62] print.check_T_and_F*
[63] print.check_code_usage_in_package*
[64] print.check_compiled_code*
[65] print.check_demo_index*
[66] print.check_depdef*
[67] print.check_details*
[68] print.check_details_changes*
[69] print.check_doi_db*
[70] print.check_dotInternal*
[71] print.check_make_vars*
[72] print.check_nonAPI_calls*
[73] print.check_package_CRAN_incoming*
[74] print.check_package_code_assign_to_globalenv*
[75] print.check_package_code_attach*
[76] print.check_package_code_data_into_globalenv*
[77] print.check_package_code_startup_functions*
[78] print.check_package_code_syntax*
[79] print.check_package_code_unload_functions*
[80] print.check_package_compact_datasets*
[81] print.check_package_datasets*
[82] print.check_package_depends*
[83] print.check_package_description*
[84] print.check_package_description_encoding*
[85] print.check_package_license*
[86] print.check_packages_in_dir*
[87] print.check_packages_used*
[88] print.check_po_files*
[89] print.check_so_symbols*
[90] print.check_url_db*
[91] print.check_vignette_index*
[92] print.citation*
[93] print.codoc*
[94] print.codocClasses*
[95] print.codocData*
[96] print.colorConverter*
[97] print.compactPDF*
[98] print.condition
[99] print.connection
[100] print.data.frame
[101] print.default
[102] print.dendrogram*
[103] print.density*
[104] print.difftime
[105] print.dist*
[106] print.dummy_coef*
[107] print.dummy_coef_list*
[108] print.ecdf*
[109] print.eigen
[110] print.factanal*
[111] print.factor
[112] print.family*
[113] print.fileSnapshot*
[114] print.findLineNumResult*
[115] print.formula*
[116] print.fseq*
[117] print.ftable*
[118] print.function
[119] print.getAnywhere*
[120] print.glm*
[121] print.hclust*
[122] print.help_files_with_topic*
[123] print.hexmode
[124] print.hsearch*
[125] print.hsearch_db*
[126] print.htest*
[127] print.html*
[128] print.html_dependency*
[129] print.htmlwidget*
[130] print.infl*
[131] print.integrate*
[132] print.isoreg*
[133] print.kmeans*
[134] print.libraryIQR
[135] print.listof
[136] print.lm*
[137] print.loadings*
[138] print.loess*
[139] print.logLik*
[140] print.ls_str*
[141] print.medpolish*
[142] print.mtable*
[143] print.news_db*
[144] print.nls*
[145] print.noquote
[146] print.numeric_version
[147] print.object_size*
[148] print.octmode
[149] print.packageDescription*
[150] print.packageIQR*
[151] print.packageInfo
[152] print.packageStatus*
[153] print.pairwise.htest*
[154] print.pdf_doc*
[155] print.pdf_fonts*
[156] print.pdf_info*
[157] print.person*
[158] print.power.htest*
[159] print.ppr*
[160] print.prcomp*
[161] print.princomp*
[162] print.proc_time
[163] print.raster*
[164] print.recordedplot*
[165] print.restart
[166] print.rle
[167] print.roman*
[168] print.sessionInfo*
[169] print.shiny.tag*
[170] print.shiny.tag.list*
[171] print.simple.list
[172] print.smooth.spline*
[173] print.socket*
[174] print.srcfile
[175] print.srcref
[176] print.stepfun*
[177] print.stl*
[178] print.subdir_tests*
[179] print.summarize_CRAN_check_status*
[180] print.summary.aov*
[181] print.summary.aovlist*
[182] print.summary.ecdf*
[183] print.summary.glm*
[184] print.summary.lm*
[185] print.summary.loess*
[186] print.summary.manova*
[187] print.summary.nls*
[188] print.summary.packageStatus*
[189] print.summary.ppr*
[190] print.summary.prcomp*
[191] print.summary.princomp*
[192] print.summary.table
[193] print.summaryDefault
[194] print.suppress_viewer*
[195] print.table
[196] print.tables_aov*
[197] print.terms*
[198] print.ts*
[199] print.tskernel*
[200] print.tukeyline*
[201] print.tukeysmooth*
[202] print.undoc*
[203] print.vignette*
[204] print.warnings
[205] print.xgettext*
[206] print.xngettext*
[207] print.xtabs*
在上述的长列表中,有一些重要的方法,如print.factor()。当我们通过函数print()打印一个因子时,调用会自动分配给print.factor()
创建的类为-bank,会搜索一个名为print.bank()的方法,由于没有这样的方法存在,所以使用print.default()。
通用函数有一个默认方法,在没有匹配的情况下使用。
创建你自己的方法
创建你自己的方法是可能的。
现在,如果类–‘银行’搜索print.bank(),它会找到这个方法并使用它,如果我们已经创建了它。
x <- list(name ="Arjun", account_no = 1234,
saving = 1500, withdrawn = 234)
class(x)<-"bank"
print.bank<-function(obj)
{
cat("Name is ", objname, "\n")
cat(objaccount_no, " is the Acc no of the holder\n ")
cat(objsaving, " is the amount of saving in the account \n ")
cat(objwithdrawn, " is the withdrawn amount\n")
}
x
输出:
Name is Arjun
1234 is the Acc no of the holder
1500 is the amount of saving in the account
234 is the withdrawn amount
在一般情况下,创建方法现在可以很容易定义和理解。
- 首先定义一个存在于类之外的函数(以通用方式)。
- 其次,一个给定的类定义该函数的具体内容。
基于函数的一个参数的类名和写在相关函数名称中的后缀,R环境决定使用哪个函数。
# Defining a function
indian <- function(eatslunch = TRUE, myFavorite ="daal")
{
me <- list(haslunch = eatslunch,
favoritelunch = myFavorite)
# Set the name for the class
class(me) <- append(class(me), "indian")
return(me)
}
# Reserving the name of the function and
# by using the command <code>UseMethod</code>
# R will search for the appropriate function.
setHaslunch <- function(e, newValue)
{
print("Calling the base setHaslunch function")
UseMethod("setHaslunch", e)
print(" this is not executed")
}
setHaslunch.default <- function(e, newValue)
{
print("This objects is unable to be handled.")
return(e)
}
setHaslunch.indian <- function(e, newValue)
{
print("R is in setHaslunch.indian and is setting the value")
ehaslunch <- newValue
return(e)
}
# objects calling functions
foodie <- indian()
foodiehaslunch
foodie <- setHaslunch(foodie, FALSE)
foodie$haslunch
输出:
[1] TRUE
[1] "Calling the base setHaslunch function"
[1] "R is in setHaslunch.indian and is setting the value"
[1] FALSE
属性
对象的属性不影响对象的值,但它们是用于处理对象的额外信息。
函数 attributes() 可以用来查看对象的属性。
例子:一个S3对象被创建,它的属性被显示
# Defining a function
x <- list(name ="Arjun", percentage = 95,
school_name ="ST Xavier")
attributes(x)
输出:
$names
[1] "name" "percentage" "school_name"
$class
[1] "resume"
另外,你可以通过使用attr,为一个对象添加属性。
# Defining a function
x <- list(name ="Arju", percentage = 95,
school_name ="ST Xavie")
attr(x, "age")<-c(18)
attributes(x)
输出:
$names
[1] "name" "percentage" "school_name"
$age
[1] 18
S3被命名为S3,因为它起源于S语言的第三个版本。S是一种编程语言,后来修改为R和S plus。