+4

Thử viết shell script theo dạng hướng đối tượng

Bài viết được dịch từ nguồn http://hipersayanx.blogspot.com/2012/12/object-oriented-programming-in-bash.html

Bash rất phổ biến và đó là ngôn ngữ lập trình tập trung vào việc thực hiện lệnh. Lập trình hướng đối tượng (OOP) là một mô hình lập trình hướng tới một đối tượng với một tập các thuộc tính và hành động mà nó có thể thực hiện. Nếu bạn sử dụng Bash để viết các chương trình đơn giản và ngắn, lập trình thủ tục thì bạn không cần nhiều hơn. Nhưng nếu chương trình của bạn ngày càng trở nên lớn hơn, một chương trình to lớn (> 1000 dòng), thì bạn cần một cách tốt hơn để cấu trúc chương trình của bạn để giúp duy trì và đọc dễ dàng. Tất nhiên, Bash thiếu các tính năng OOP, nhưng với một số thủ thuật bạn có thể mô phỏng nó với một vài dòng được thêm vào, và tôi sẽ chỉ cho bạn làm thế nào.

Chú ý: Bạn cần có khái niệm vững chắc về OOP và Bash trước khi đọc, tôi sẽ không giải thích điều này ở đây.

Đầu tiên tạo ra một chương trình mà trong đó bạn sẽ xác định lớp đối tượng của bạn, và cho phép nó thực hiện các method.

touch vector.sh
chmod +x vector.sh

Sau đó sao chép đoạn code sau:

#!/bin/bash
 
# Base class. (1)
function Vector()
{
    # A pointer to this Class. (2)
    base=$FUNCNAME
    this=$1
 
    # Inherited classes (optional). (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
 
    # Declare Properties. (4)
    export ${this}_x=$2
    export ${this}_y=$3
    export ${this}_z=$4
 
    # Declare methods. (5)
    for method in $(compgen -A function)
    do
        export ${method/#$base\_/$this\_}="${method} ${this}"
    done
}
 
# Human readable representation of the 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)"
}
 
# Adds two vectors.
function Vector_add()
{
    base=$(expr "$FUNCNAME" : '\([a-zA-Z][a-zA-Z0-9]*\)')
    this=$1
    other=$2
 
    # Get it's components
    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")
 
    # Add it's components
    x=$(($x1 + $x2))
    y=$(($y1 + $y2))
    z=$(($z1 + $z2))
 
    # Create a new vector. (8)
    Vector 'vector3' $x $y $z
 
    $vector3_show
}
  1. Đây hàm của một class. Nó phải có cùng tên của class. Tên của một class không thể chứa dấu gạch dưới (_). Chúng ta sẽ sử dụng hàm này để tạo các method của lớp "Vector".

  2. Ở đây bạn có thể có được một base class của đối tượng và một tham chiếu của đối tượng được tạo ra. Đối số đầu tiên của hàm tạo phải luôn là tên của đối tượng để tạo ra.

  3. Khối code này mô phỏng thừa kế, bạn có thể gỡ bỏ nó nếu bạn không cần. 3.1. Mỗi thuộc tính và phương thức của lớp có thể được gọi như $ {this} _methodProperty_name, hoặc bạn cũng có thể gọi nó là lớp cơ sở như $ {base} _methodProperty_name. Nhiều class thừa kế overide các phương thức và thuộc tính (m & p) của các class trước như sau: 3.2. Điều này sẽ export m & p của base class như m & p của class.

  4. Mỗi phương thức và thuộc tính của lớp được xuất ra như là một biến global dưới dạng objectName_methodProperty_name. Bạn có thể khởi tạo các thuộc tính thông qua các tham số, hoặc với một giá trị mặc định, hoặc để nó không bắt buộc.

  5. Điều này sẽ tìm thấy tất cả các function với prefixBaseClass_ * và tạo nó như là một biến global thay thế BaseClass với tên của đối tượng, giá trị của biến sẽ là một chuỗi với functionlớp cơ sở và tên class là tham số đầu tiên đóng vai trò là một tham chiếu Với nó.

  6. Các function của lớp được định nghĩa là BaseClass_methodName. Tên function có thể chứa dấu gạch dưới, camelCase được khuyến khích.

  7. Lấy một tham chiếu đến base class (không bắt buộc) và đối tượng, đối số đầu tiên là tên đối tượng.

  8. Tất nhiên, bạn có thể tạo các đối tượng mới bên trong các function của cùng một lớp.

Để sử dụng các class. Tạo một phần mềm từ đó bạn sẽ sử dụng class mà bạn đã định nghĩa:

#!/bin/bash
 
# Import the class definition file.
. vector.sh
 
function main()
{
    # Create the vectors objects. (1)
    Vector 'vector1' 1 2 3
    Vector 'vector2' 7 5 3
 
    # Show it's properties. (2)
    echo "vector1 ($vector1_x, $vector1_y, $vector1_z)"
    echo "vector2 ($vector2_x, $vector2_y, $vector2_z)"
 
    # Call to it's methods.
    $vector1_show
    $vector2_show
 
    $vector1_add vector2
}
 
main

1.Các đối tượng được khai báo là đối tượng class objectName [arg1 arg2 arg3 ...]. 2.Bây giờ bạn có thể gọi các function và thuộc tính như $ objectName_methodsProperty_name [arg1 arg2 arg3 ...].

Kết qủa là:

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

OOP trong Bash đã được tạo. Thành tựu đạt được: D (OOP in Bash unlocked. Achievement reached 😄)

Cảm ơn và hi vọng bài viết có ích cho công việc của bạn.


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.