R语言 面向对象的编程

R语言 面向对象的编程

在这篇文章中,我们将讨论R编程语言中的面向对象编程(OOPs)。我们将讨论S3和S4类,这些类的继承性,以及这些类提供的方法。

在R编程中,OOPs提供类和对象作为其关键工具,以减少和管理程序的复杂性。R是一种使用OOPs概念的功能语言。我们可以把一个类看作是一辆汽车的草图。它包含了所有关于车型名称、车型编号、发动机等的细节。基于这些描述,我们选择一辆汽车。汽车是一个对象。每个汽车对象都有自己的特点和特征。一个对象也被称为一个类的实例,创建这个对象的过程被称为实例化。在R语言中,S3和S4类是面向对象编程的两个最重要的类。但在讨论这些类之前,让我们先看看关于类和对象的简介。

类和对象

类是一个蓝图或原型,通过封装数据成员和函数,对象是由它构成的。一个对象是一个数据结构,它包含一些作用于其属性的方法。

R - 面向对象的编程

S3类

S3类没有预定义的定义,能够进行调度。在这个类中,通用函数对方法进行了调用。轻松实现S3是可能的,因为它不同于传统的编程语言Java、C++和C#,后者实现了面向对象的消息传递。

创建S3类

为了创建这个类的一个对象,我们将创建一个包含所有类成员的列表。然后将这个列表作为参数传递给class()方法。

语法

variable_name <- list(attribute1, attribute2, attribute3....attributeN)

例子

在下面的代码中,定义了一个学生类。给出了一个适当的类名,其属性是学生的姓名和学号。然后,学生类的对象被创建和调用。

# List creation with its attributes name
# and roll no.
a < - list(name="Adam", Roll_No=15)
 
# Defining a class "Student"
class(a) < - "Student"
 
# Creation of object
a
R

输出

$name
[1] "Adam"

$Roll_No
[1] 15

attr(, "class")
[1] "Student"
R

泛型函数

通用函数是多态性的一个好例子。为了理解通用函数的概念,请考虑print()函数。print()函数是各种打印函数的集合,这些函数是为R编程语言中不同的数据类型和数据结构创建的。它根据作为参数传递的对象的类型,调用适当的函数。我们可以通过methods()函数看到打印函数的各种实现。

例子: 看到不同类型的打印函数

methods(print)
R

输出

R - 面向对象的编程

现在让我们创建一个属于我们自己的通用函数。我们将为我们的类创建打印函数,它将以我们指定的格式打印所有的成员。但在创建打印函数之前,让我们先创建打印函数对我们类的作用。

例子

# List creation with its attributes name
# and roll no.
a = list(name="Adam", Roll_No=15)
 
# Defining a class "Student"
class(a) = "Student"
 
# Creation of object
print(a)
R

输出

$name
[1] "Adam"

$Roll_No
[1] 15

attr(,"class")
[1] "Student"
R

现在让我们以我们指定的格式打印所有的成员。考虑一下下面的例子 –

例子

print.Student <- function(obj){
  cat("name: " ,objname, "\n")
  cat("Roll No: ", objRoll_No, "\n")
}
 
print(a)
R

输出

name:  Adam 
Roll No:  15 
R

属性

对象的属性不影响对象的值,但它们是用于处理对象的额外信息。函数attributes()可以用来查看一个对象的属性。

例子: 一个S3对象被创建,其属性被显示。

attributes(a)
R

输出

$names
'name''Roll_No'
$class
'Student'
R

另外,你可以通过使用attr来给一个对象添加属性。

attr(a, "age")<-c(18)
attributes(a)
R

输出

$names
'name''Roll_No'
$class
'Student'
$age
18
R

S3类中的继承性

继承是OOP(面向对象编程)的一个重要概念,它允许一个类派生出另一个类的特征和功能。这个特点有利于代码的重复使用。

R编程语言中的S3类没有正式和固定的定义。在一个S3对象中,一个带有其类属性的列表被设置为一个类名。S3类对象只继承其基类的方法。

例子

在下面的代码中,使用S3类进行了继承,首先创建了学生类的对象。

# student function with argument
# name(n) and roll_no(r)
student < - function(n, r) {
    value < - list(name=n, Roll=r)
    attr(value, "class") < - "student"
    value
}
R

然后,该方法被定义为打印学生的详细信息。

# 'print.student' method created
print.student < - function(obj) {
 
    # 'cat' function is used to concatenate
    # strings
    cat("Name:", objname, "\n")
    cat("Roll", objroll, "\n")}
R

现在,在创建另一个类时,通过做**class(obj) <- c(child, parent) **来完成继承。

s < - list(name="Kesha", Roll=21, country="India")
 
# child class 'Student' inherits
# parent class 'student'
class(s) < - c("Student", "student")
s
R

输出

Name: Kesha 
Roll: 21 
R

下面的代码覆盖了类student的方法。

# 'Student' class object is passed
# in the function of class 'student'
 
print.student < - function(obj) {
    cat(objname, "is from", objcountry, "\n")
}
s
R

输出

Kesha is from India
R

S4类

S4类有一个预定义的定义。它包含了定义方法和泛型的功能。它使多次派发变得容易。这个类包含用于定义方法和泛型的辅助函数。

创建S4类和对象

setClass() 命令被用来创建S4类。以下是setclass命令的语法,它用包含名称和rollno的槽来表示我的类。

语法

setClass("myclass", slots=list(name="character", Roll_No="numeric")

new() 函数用于创建一个S4类的对象。在这个函数中,我们将传递类的名称以及槽的值。

例子

# Function setClass() command used
# to create S4 class containing list of slots.
setClass("Student", slots=list(name="character",
                               Roll_No="numeric"))
 
# 'new' keyword used to create object of
# class 'Student'
a <- new("Student", name="Adam", Roll_No=20)
 
# Calling object
a
R

输出

Slot "name":
[1] "Adam"

Slot "Roll_No":
[1] 20
R

从生成器函数创建S4对象

setClass()返回一个生成器函数,该函数有助于创建对象,它就像一个构造函数。

例子

stud <- setClass("Student", slots=list(name="character",
                               Roll_No="numeric"))
 
# Calling object
stud
R

输出

new(“classGeneratorFunction”, .Data = function (…)

new(“Student”, …), className = structure(“Student”, package = “.GlobalEnv”),

package = “.GlobalEnv”)
Bash

现在,上述创建的stud函数将作为学生类的构造函数。它将表现为new()函数。

例子

stud(name="Adam", Roll_No=15)
R

输出

An object of class "Student"
Slot "name":
[1] "Adam"

Slot "Roll_No":
[1] 15
R

S4类中的继承性

R编程中的S4类有适当的定义,派生类将能够继承其基类的属性和方法。为此,我们将首先创建一个带有适当槽的基类,并为该类创建一个通用函数。然后我们将创建一个派生类,它将使用包含参数来继承。派生类将继承基类中的成员和函数。

例子

# Define S4 class
setClass("student",
         slots=list(name="character",
                    age="numeric", rno="numeric")
         )
 
# Defining a function to display object details
setMethod("show", "student",
          function(obj){
              cat(obj@name, "\n")
              cat(obj@age, "\n")
              cat(obj@rno, "\n")
          }
          )
 
# Inherit from student
setClass("InternationalStudent",
         slots=list(country="character"),
         contains="student"
         )
 
# Rest of the attributes will be inherited from student
s < - new("InternationalStudent", name="Adam",
          age=22, rno=15, country="India")
show(s)
R

输出

Adam 
22 
15
R

同时定义S3和S4类的原因 如下。

  • 如果直接调用S3泛型函数,将不会单独看到S4类。例如,如果某个函数从一个包中调用 unique() ,而这个包并没有让该函数成为S4泛型,就会出现这种情况。
  • 然而,原始函数和运算符是例外。内部C代码将寻找S4方法,如果且仅当对象是一个S4对象。S4方法调度将用于调度任何二进制运算符的调用,其中任何一个操作数是S4对象。
  • 如果有任何符合条件的非默认的S4方法,S3类将不会被单独调用。

因此,如果一个包为一个S4类定义了一个唯一的S3方法,但另一个包为该类的超类定义了一个S4方法,那么超类的方法将被选择,可能不是原意。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程