S3 类是 R 编程语言中最流行的类。
它简单易实现,因此 R 中预定义的大多数类都属于此类型。
在 R 中创建 S3 类和对象
创建 S3 类
首先我们创建一个包含各种组件的列表,然后使用 class()
函数创建一个类。例如,
# create a list with required components
employee1 <- list(name = "Peter", age = 21, role = "Developer")
# form class of employee1 list and
# name the class appropriately
class(employee1) <- "Employee_Info"
在这里,我们首先创建了一个名为 employee1 的列表,其中包含所需的组件。
然后我们使用 class(employee1)
形成了 employee1 的类,并将该类命名为 Employee_Info
。
现在我们可以创建这个类的一个对象。
创建 S3 对象
S3 对象本质上是一个列表,其类属性被分配了一些名称。我们使用列表的名称来创建和调用我们创建的对象。
要创建和调用上面类的对象,我们只需使用列表名称 employee1。例如,
# create and call an object
employee1
在这里,我们已成功创建并调用了 Employee_Info
类的一个对象。
示例:R S3 类
# create a list with required components
employee1 <- list(name = "Peter", age = 21, role = "Developer")
# form class of employee1 list and
# name the class appropriately
class(employee1) <- "Employee_Info"
# create and call an object
employee1
输出
$name [1] "Peter" $age [1] 21 $role [1] "Developer" attr(,"class") [1] "Employee_Info"
在上面的示例中,我们创建了一个名为 employee1 的列表,其中包含三个组件。
这里,Employee_Info
是类的名称。为了创建这个类的一个对象,我们将 employee1 列表传递到 class()
中。
最后,我们创建了 Employee_Info
类的一个对象,并将其命名为 employee1。
R 中的 S3 泛型函数和方法
泛型函数由多个函数组成,这些函数为不同类型实现相同的操作。
在上面的示例中,我们简单地使用对象名称来打印类属性。在交互模式下,单独写入名称将使用 print()
函数打印它。
# create and call object without print()
employee1
# create and call object with print()
print(employee1)
在这里,两种情况的输出都将相同
此外,我们可以将 print()
与 向量、数据框、因子 等一起使用,它们会根据所属的类以不同的方式打印。
print()
如何知道如何打印这些种类繁多的不同对象?
答案是,print()
是一个泛型函数。实际上,它包含许多方法的集合。
您可以使用以下方式检查所有这些方法
# to display all available methods
methods(print)
输出
[1] print.Arima* [2] print.AsIs [3] print.Bibtex* ... ... [184] print.xgettext* [185] print.xngettext* [186] print.xtabs*
在这里,methods()
函数将显示 print
的所有可用方法,共 186 个。
我们可以在上面的列表中看到 print.factor
和 print.data.frame
等方法。
当我们对因子调用 print()
时,它会分派给 print.factor()
。在这里,我们可以观察到方法名称的形式是 generic_name.class_name()
。
这就是 R 如何根据类来确定要调用哪个方法。
打印我们的 Employee_Info
类对象会查找 print.Employee_Info()
形式的方法,但没有这种形式的方法。
那么,我们的 Employee_Info
类对象调用了哪个方法呢?
它调用了 print.default()
。这是在没有找到其他匹配项时调用的备用方法。泛型函数都有一个默认方法。
在 R 中编写自己的方法
由于我们上面讨论过没有 print.Employee_Info()
方法。我们将尝试自己实现 print.Employee_Info()
方法。
print.Employee_Info <- function(obj) {
cat(obj$name, "\n")
cat(obj$age, "years old\n")
cat("Role:", obj$role, "\n")
}
在这里,我们创建了一个名为 print.Employee_Info()
的方法。我们将 obj
作为参数传递。
我们使用了 obj
和 $
来获取 Employee_Info
类的 name
、age
和 role
属性的值。
现在,每当我们 print()
一个 Employee_Info
类的对象时,就会调用此方法。
# create a list with required components
employee1 <- list(name = "Peter", age = 21, role = "Developer")
# form class of employee1 list and
# name the class appropriately
class(employee1) <- "Employee_Info"
print.Employee_Info <- function(obj) {
cat(obj$name, "\n")
cat(obj$age, "years old\n")
cat("Role:", obj$role, "\n")
}
print(employee1)
输出
Peter 21 years old Role: Developer
在这里,每当我们 print()
一个 Employee_Info
类的对象时,都会调用 print.Employee_Info()
。
我们也可以像这样使用 print.Employee_Info()
方法
print.Employee_Info(employee1)
输出将相同。