• Suscríbete al Feed Espacio Linux
  • Suscríbete al Feed por Email
  • Sigue a Espacio Linux en Identi.ca
  • Espacio Linux también en Facebook
  • Sigue a Espacio Linux en Twitter
  • Sigue a Espacio Linux en Google +
          Iniciar sesión | Registrarse

Programación orientada a Objetos en Bash

Bash es una shell de *nix muy común, y su lenguaje de programación es puramente procedural y enfocado a la ejecución de comandos. La Programación orientada a Objetos (POO) es un paradigma de programación el cual representa los elementos de un problema como entidades con un conjunto de propiedades y acciones que puede ejecutar. Si usas Bash para escribir scripts cortos y simples, con la programación procedural estas bastante bien, no necesitas más. Pero si tu programa se vuelve más y mas grande, un programa monstruoso (> 1000 lineas), entonces necesitas una mejor forma de estructurar tu programa para hacerlo más fácil de mantener y leer. Por supuesto, Bash no ofrece ninguna característica de POO, pero se pude simular usando algunos trucos y agregando solo unas pocas lineas, y te voy a mostrar como.

Concepto de Programación orientada a Objetos

Concepto de Programación orientada a Objetos


ATENCIÓN: Necesitas tener conceptos sólidos de POO y Bash antes de leer esto, no voy a explicar nada de ello aquí.

Primero que nada, crea un script en el cual definirás tu clase, y dale permisos de ejecución.

1
2
touch vector.sh
chmod +x vector.sh

Entonces copia el siguiente código en tu script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#!/bin/bash

# Clase base. (1)
function Vector()
{
    # Un puntero a esta clase. (2)
    base=$FUNCNAME
    this=$1

    # Herencia de clases (opcional). (3)
    export ${this}_inherits="Class1 Class2 Class3" # (3.1)

    for class in $(eval "echo \$${this}_inherits")
    do
        for property in $(compgen -A variable ${class}_)
        do
            export ${property/#$class\_/$this\_}="${property}" # (3.2)
        done

        for method in $(compgen -A function ${class}_)
        do
            export ${method/#$class\_/$this\_}="${method} ${this}"
        done
    done

    # Declaramos las propiedades. (4)
    export ${this}_x=$2
    export ${this}_y=$3
    export ${this}_z=$4

    # Declaramos los métodos. (5)
    for method in $(compgen -A function)
    do
        export ${method/#$base\_/$this\_}="${method} ${this}"
    done
}

# Representación visual del vector. (6)
function Vector_show()
{
    # (7)
    base=$(expr "$FUNCNAME" : '\([a-zA-Z][a-zA-Z0-9]*\)')
    this=$1

    x=$(eval "echo \$${this}_x")
    y=$(eval "echo \$${this}_y")
    z=$(eval "echo \$${this}_z")

    echo "$this ($x, $y, $z)"
}

# Suma de vectores.
function Vector_add()
{
    base=$(expr "$FUNCNAME" : '\([a-zA-Z][a-zA-Z0-9]*\)')
    this=$1
    other=$2

    # Obtenemos sus componentes
    x1=$(eval "echo \$${this}_x")
    y1=$(eval "echo \$${this}_y")
    z1=$(eval "echo \$${this}_z")

    x2=$(eval "echo \$${other}_x")
    y2=$(eval "echo \$${other}_y")
    z2=$(eval "echo \$${other}_z")

    # Sumamos sus componentes
    x=$(($x1 + $x2))
    y=$(($y1 + $y2))
    z=$(($z1 + $z2))

    # Creamos un nuevo vector. (8)
    Vector 'vector3' $x $y $z

    $vector3_show
}

Explicación

  1. Esta función es un equivalente del constructor de una clase. Debe tener el mismo nombre que la clase. El nombre de la clase no puede contener guiones bajos (_). Vamos a usar esta función para crear instancias de la clase “Vector”.
  2. Aquí obtenemos una referencia de la clase base del objeto y una referencia del objeto creado. El primer argumento del constructor debe ser siempre el nombre del objeto a crear.
  3. Este bloque de código simula la herencia múltiple, es opcional y lo puedes remover si no lo necesitas.
    1. Cada método y propiedad de la clase se puede acceder como ${this}_nombreDel_metodoPropiedad, o también puedes llamar a la clase base como ${base}_nombreDel_metodoPropiedad.
      La herencia múltiple funciona sobrescribiendo los métodos y propiedades (myp) de las clases precedentes como se explica a continuación:

      Class1 < Class2 < Class3 < Base
      • Class2 sobrescribe los myp de Class1.
      • Class3 sobrescribe los myp de Class1 y Class2.
      • Base sobrescribe los myp de Class1, Class2 y Class3.
    2. Esto exportará los myp de la clase base como myp del objeto. Leer más abajo.
  4. Cada método y propiedad de la clase se exporta como variable global en la form nombreDelObjeto_nombreDel_metodoPropiedad. Puedes inicializar las propiedades a través de los parámetros del constructor, o mediante un valor predefinido, o dejarlo sin inicializar.
  5. Esto buscará cada función con el patrón ClaseBase_* y lo exportará como variable global reemplazando ClaseBase con el nombre del objeto, el valor de la variable será una cadena con el método de la clase base y el nombre del objeto como primer parámetro que sirve de referencia al mismo.
  6. Los métodos de la clase se definen como ClaseBase_nombreDelmetodo. Los nombres de los métodos pueden contener guiones bajos, pero se recomienda usar camelCase.
  7. Obtiene una referencia a la clase base (no es obligatorio) y el objeto, recuerden que el primer argumento es el nombre del objeto.
  8. Por supuesto, Puedes crear nuevos objetos dentro de los métodos de la misma clase.

Estamos listos para usar nuestra clase. Creamos un script desde el cual usaremos nuestra clase, dale permisos de ejecución, y copia el siguiente código a dentro de este:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/bin/bash

# Importamos el archivo con la definición de la clase.
. vector.sh

function main()
{
    # Crea los objetos vectores. (1)
    Vector 'vector1' 1 2 3
    Vector 'vector2' 7 5 3

    # Muestra sus propiedades. (2)
    echo "vector1 ($vector1_x, $vector1_y, $vector1_z)"
    echo "vector2 ($vector2_x, $vector2_y, $vector2_z)"

    # Llama a sus métodos.
    $vector1_show
    $vector2_show

    $vector1_add vector2
}

main

Explicación

  1. Los objetos se declaran como Clase nombreDelObjeto [arg1 arg2 arg3 …].
  2. Ahora puedes acceder a sus métodos y propiedades como $nombreDelObjeto_nombreDel_metodoPropiedad [arg1 arg2 arg3 …].

El resultado de la ejecución del script es:

1
2
3
4
5
6
$ ./main.sh
vector1 (1, 2, 3)
vector2 (7, 5, 3)
vector1 (1, 2, 3)
vector2 (7, 5, 3)
vector3 (8, 7, 6)

POO en Bash desbloqueado. logro conseguido :D


Temas:
Documentación, Programación


Etiquetas:
,

Feed Espacio LinuxSi este artículo ha sido de tu interés, considera hacer un comentario o suscribirte al feed para que te enteres de nuevos artículos a través de tu lector de noticias o email.

Acerca del autor

2 Comentarios para “Programación orientada a Objetos en Bash”

  1. Excelente tutorial!!! ya lo voy a poner en practica :-)

  2. Wua me sulucionaste u gran problema porque me encanta la programacion en shell srting pero despues de tiempo de progrmar me di cuenta de que la POO podia hacer programas muy potentes pero me costaba aprender otros lenguajes gracias

Publica un comentario

Puedes usar estas etiquetas XHTML: <a href="" title=""> <abbr title=""> <acronym title=""> <blockquote cite=""> <code> <em> <strong>