Cómo programar la programación orientada a objetos en lenguaje R — Tipo S4

1 Entender el lenguaje R

La orientación a objetos es una forma de comprender y abstraer el mundo real.Cuando la complejidad del código aumenta y es difícil de mantener, la orientación a objetos se vuelve muy importante. R es principalmente para cálculos estadísticos, y la cantidad de código generalmente no es muy grande, docenas de líneas, cientos de líneas, el uso de métodos de programación orientados a procesos puede completar la tarea de programación.
Sin embargo, a medida que se unían más y más personas con experiencia en ingeniería, el lenguaje R comenzó a desarrollarse en más campos. El método de codificación original orientado a procesos con una pequeña cantidad de código será cada vez más difícil de mantener proyectos de código masivos, por lo que debe haber un nuevo método de programación para codificar las ideas originales de codificación orientadas a procesos. Este nuevo método de programación es objeto- Programación orientada (Programación Orientada a Objetos, POO).
Hay clases S3 y S4 en el lenguaje R. La clase S3 es ampliamente utilizada, simple y tosca de crear pero flexible, mientras que la clase S4 es más refinada y tiene una estructura de clases estricta. Los usuarios de otros idiomas pueden estar acostumbrados a eso. El sistema de objetos S4 tiene características estructurales obvias y es más adecuado para la programación orientada a objetos. La comunidad de Bioconductores utiliza el sistema de objetos S4 como su infraestructura y solo acepta paquetes R que se ajustan a la definición de S4.

2 creación de clase S4-setClass ()

Dado que el objeto S4 es una implementación estándar orientada a objetos, hay una definición de clase especial setClass () y una función de instanciación de clase new () . La función setClass se declara de la siguiente manera:

setClass (Clase, ranuras, prototipo, contiene = carácter (), validez, sellado)

El significado de cada parámetro:

Clase Nombre de clase definido
ranuras Definir atributos y tipos, los parámetros son lista
prototipo El valor predeterminado de la propiedad
contiene Clase padre heredada
validez Definir la verificación del tipo de atributo
sellado Si se establece en TRUE, la clase con el mismo nombre no se puede volver a definir.
#定义一个 人 类
setClass(
  "person", 
  slots=list(name="character", age="numeric"),
  prototype = list(name="nobody", age=20)
)
# new()实例化一个人 
zhangsan <- new(Class ="person", name="zhangsan", age = 26)
# 查看 zhangsan的属性 
zhangsan
An object of class "person"
Slot "name":
[1] "zhangsan"

Slot "age":
[1] 26
# zhangsan 属于person类
class(zhangsan)
[1] "person"
attr(,"package")
[1] ".GlobalEnv"
#另外,S4中我们只能使用@来访问一个对象的属性 
zhangsan@name
> [1] "zhangsan"

3 Verificación de tipo de la clase S4 — setValidity ()

La categoría s4 incluye verificación de tipo obligatoria, si el tipo de inicialización es diferente del tipo de definición, no se puede pasar, como

# name 传入的不是字符串
lisi <- new(Class ="person", name=11, age = 22)
Error in validObject(.Object) : 
  类别为“person”的对象不对: invalid object for slot "name" in class "person": got class "numeric", should be or extend class "character"

También puede utilizar la función setValidity () para establecer comprobaciones de validez adicionales, como la edad no puede ser negativa,

setValidity("person", function(object){
    
    
  if (object@age <= 0) stop("Age is negative")
})
# age 传入负数
> lisi <- new(Class ="person", name="lisi", age = -1)
 Error in validityMethod(object) : Age is negative 

4 Funciones genéricas de la clase S4

Las funciones genéricas son populares con el mismo nombre de función, lo que produce diferentes efectos cuando se encuentran diferentes objetos.
Las funciones genéricas de S4 usan ** setGeneric () ** para definir interfaces genéricas y setMethod () para definir clases de realidad. Esto permite que el sistema de objetos S4 esté más en línea con las características orientadas a objetos. El siguiente ejemplo ilustra qué función genérica

# 设定一个函数来 自我介绍 
# 普通函数 
selfIntroduce<- function(name){
    
    
  sprintf("my name is %s", name)
}
selfIntroduce("Sun wukong")
>"my name is Sun wukong" 
# 将函数定义为泛型函数,即接口
setGeneric("selfIntroduce",
           function(object){
    
    
             standardGeneric("selfIntroduce")
          }
)
selfIntroduce("Sun wukong")# 这时普通函数已经不能使用了, 泛型函数必须指定具体类的方法
#Error in (function (classes, fdef, mtable)  : 
# unable to find an inherited method for function ‘selfIntroduce’ for signature #‘"character"’ 

# 定义函数的现实,并指定参数类型为person对象时如何运行
setMethod("selfIntroduce", 
          signature(object = "person"),
          function(object){
    
    
            sprintf("my name is %s, i'm %d years old", object@name, object@age)
          }
)
selfIntroduce(zhangsan)
>"my name is zhangsan, i'm 26 years old"
# 增加一个函数的现实,指定参数类型为character对象时如何运行
setMethod("selfIntroduce", 
          signature(object = "character"),
          function(object){
    
    
            sprintf("my name is %s", object)
          }
)
selfIntroduce("Sun wukong")
>"my name is Sun wukong" 
# 查看类函数
> showMethods(selfIntroduce)
Function: selfIntroduce (package .GlobalEnv)
object="character"
object="Person"

# 查看类函数定义
getMethod("selfIntroduce", "Person")
Method Definition:

function (object) 
{
    
    
    sprintf("my name is %s, i'm %d years old", object@name, 
        object@age)
}

Signatures:
        object  
target  "Person"
defined "Person"

Puede ver que los genéricos utilizan métodos diferentes cuando se encuentran con el mismo objeto

5 Herencia de la clase S4

Para heredar una clase, use el parámetro contiene en setClass () para especificar la clase padre

#新建 student 类, 继承 person 类。 
setClass(Class = "student",
         slots=list( school="character", major="character", father="person"),
         contains="person")
xiaoming<- new(Class ="student", 
			    name = "xiaoming", 
			    age = 18, 
			    school="qinghuauni", 
			    major = "computer science",
			    father = zhangsan
		   )

Supongo que te gusta

Origin blog.csdn.net/weixin_43705953/article/details/115348720
Recomendado
Clasificación