跳到主要内容

R S3类

提示
  1. 创建 S3 类和对象:在 R 中,S3 类通过创建一个列表并为其指定一个类名来创建,如 class(employee1) <- "Employee_Info"。S3 对象本质上是一个带有类属性的列表,通过列表名称创建和调用。
  2. 泛型函数和方法print() 是一个泛型函数,包含多个方法来处理不同类型的对象。使用 methods(print) 可查看所有可用的 print 方法。对于自定义类(如 Employee_Info),如果没有特定的打印方法,则会调用 print.default()
  3. 自定义方法:可以为特定类编写自定义方法,例如 print.Employee_Info(),用于定义该类对象的打印行为。此方法在调用 print() 时自动应用于 Employee_Info 类的对象。

S3 类是 R 编程语言中最受欢迎的类。

它简单易实现,因此 R 中预定义的大多数类都是这种类型。

在 R 中创建 S3 类和对象

创建 S3 类

首先我们创建一个包含各种组件的列表,然后使用 class() 函数创建一个类。例如,

# 创建一个包含所需组件的列表
employee1 <- list(name = "Peter", age = 21, role = "Developer")

# 形成 employee1 列表的类并
# 合理命名该类
class(employee1) <- "Employee_Info"

这里,我们首先创建了一个名为 employee1 的列表,包含所需的组件。

然后我们使用 class(employee1) 形成了 employee1 的一个类,并将这个类命名为 Employee_Info

现在我们可以创建这个类的一个对象。

创建 S3 对象

一个 S3 对象基本上是一个列表,其类属性被赋予了一些名称。我们使用列表的名称来创建和调用我们创建的对象。

要创建和调用上述类的对象,我们简单地使用列表名称 employee1。例如,

# 创建并调用一个对象
employee1

这里,我们已经成功地创建并调用了 Employee_Info 类的一个对象。

示例:R S3 类

# 创建一个包含所需组件的列表
employee1 <- list(name = "Peter", age = 21, role = "Developer")

# 形成 employee1 列表的类并
# 合理命名该类
class(employee1) <- "Employee_Info"

# 创建并调用一个对象
employee1

输出

$name
[1] "Peter"

$age
[1] 21

$role
[1] "Developer"

attr(,"class")
[1] "Employee_Info"

在上述示例中,我们创建了一个名为 employee1、包含三个组件的列表。

这里,Employee_Info 是类的名称。为了创建这个类的一个对象,我们在 class() 内传递了 employee1 列表。

最后,我们创建了一个 Employee_Info 类的对象,并调用了名为 employee1 的对象。

R 中的 S3 泛型函数和方法

一个泛型函数由实现对不同类型相同操作的多个函数组成。

在上述示例中,我们只是使用对象名称打印类属性。在交互模式下,单独写下名称会使用 print() 函数打印它。

# 不使用 print() 创建并调用对象
employee1

# 使用 print() 创建并调用对象
print(employee1)

这里,在两种情况下,输出将是相同的

此外,我们可以使用 print()向量数据框因子 等,它们会根据所属的类别以不同方式打印。 print() 函数如何知道如何打印这些外观不同的对象?

答案是,print() 是一个泛型函数。实际上,它包含了许多方法。

您可以使用以下方法检查所有这些方法:

# 显示所有可用的方法
methods(print)

输出

[1] print.Arima*
[2] print.AsIs
[3] print.Bibtex*
...
...
[184] print.xgettext*
[185] print.xngettext*
[186] print.xtabs*

这里,methods() 函数将显示 print 的所有可用方法,共 186 个。

我们可以在上面的列表中看到像 print.factorprint.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 类的 nameagerole 属性的值。

现在每当我们对 Employee_Info 类的对象使用 print() 时,都会调用这个方法。

# 创建一个包含所需组件的列表
employee1 <- list(name = "Peter", age = 21, role = "Developer")

# 形成 employee1 列表的类并
# 合理命名该类
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

这里,每当我们对 Employee_Info 类的对象使用 print() 时,都会调用 print.Employee_Info()

我们也可以像这样使用 print.Employee_Info() 方法:

print.Employee_Info(employee1)

输出结果将是相同的。