Ruby – Biến


Được đăng vào ngày 19/04/2016 | 6 bình luận
Ruby – Biến
4.85 (96.92%) 13 votes

Biến là nơi lưu trữ dữ liệu. Mỗi biến có một tên riêng, tên biến được đặt theo một số quy luật riêng. Mỗi biến có một kiểu dữ liệu riêng. Ruby có rất nhiều kiểu dữ liệu có sẵn. Kiểu dữ liệu trong Ruby là kiểu dữ liệu động, tức là khi chúng ta khai báo biến và gán giá trị thì Ruby sẽ tự động gán kiểu dữ liệu cho biến dựa trên giá trị đó chứ chúng ta không cần phải khai báo trước kiểu dữ liệu như trong các ngôn ngữ như C++, Java…


i = 5
puts i
i = 7
puts i

Giá trị của biến có thể thay đổi được. Trong đoạn code trên chúng ta có biến i có giá trị ban đầu là 5, sau đó thay bằng 7.

Quy tắc đặt tên biến

Tên biến là có phân biệt HOA-thường. Tức là biến age và biến Age là 2 biến khác nhau.


i = 5
p i
I = 7
p I

Trong đoạn code trên chúng ta có biến i và biến I mang các giá trị khác nhau.

5
7

Biến được đặt tên bằng các kí tự chữ cái, chữ số và dấu gạch dưới “_”, nhưng không thể bắt đầu bằng chữ số và chữ cái in hoa.


name = "Jane"
placeOfBirth = "Bratislava"
placeOfBirth = "Kosice"
favorite_season = "autumn"

n1 = 2
n2 = 4
n3 = 7

p name, placeOfBirth, favorite_season
p n1, n2, n3

Trong đoạn code trên n1, n2n3 là các tên biến hợp lệ.

Khi đặt tên biến chúng ta nên đặt tên sao cho dễ nhớ và dễ sử dụng.

Sigil

Biến trong Ruby có thể bắt đầu bằng một số kí tự đặc biệt và được gọi là sigil, các kí tự sigil dùng để chỉ ra phạm vi hoạt động của biến.


tree_name = "pine"
$car_name = "Peugeot"
@sea_name = "Black sea"
@@species = "Cat"

p local_variables
p global_variables.include? :$car_name
p self.instance_variables
p Object.class_variables

Trong đoạn code trên chúng ta có 4 biến với 4 phạm vi hoạt động khác nhau tùy theo từng kí hiệu sigil.

tree_name = "pine"

Biến không có kí tự đặc biệt nào được gọi là biến cục bộ, tức là chỉ có hiệu lực ở phạm vi trong từng phương thức, lớp… nhất định.

$car_name = "Peugeot"

Kí tự $ cho biết biến đó là biến toàn cục, biến toàn cục có hiệu lực trong toàn bộ code Ruby.

@sea_name = "Black sea"

Kí tự @ cho biết biến đó là biến instance, biến này chỉ có hiệu lực trong một đối tượng.

@@species = "Cat"

Cuối cùng là kí tự @@ tức biến class, tất cả các đối tượng của một class đều có thể truy xuất biến này.

Chúng ta sẽ tìm hiểu thêm về các loại biến này ở dưới và trong các bài sau.

p local_variables

Biến local_variables là một mảng lưu trữ toàn bộ các biến cục bộ hiện có.

p global_variables.include? :$car_name

Tương tự, chúng ta có biến global_variables lưu toàn bộ các biến toàn cục, nhưng ở đây chúng ta không cho in ra toàn bộ vì số lượng biến toàn cục có sẵn rất nhiều, thay vào đó chúng ta dùng phương thức include? để kiểm tra xem biến $car_name của chúng ta có nằm trong danh sách đó hay không.

p self.instance_variables

Ở trên chúng ta tham chiếu đến biến instance_variables, biến này lưu trữ toàn bộ biến instance trong đối tượng hiện tại, ở đây là những biến instance được khai báo trong chương trình – tức là @sea_name.

Ngoài ra ở đây chúng ta còn dùng thêm biến self nữa, biến self tham chiếu đến đối tượng hiện tại đang được sử dụng, ở đây là chương trình chính, nếu bạn đã từng làm việc với con trỏ this trong C++, Java… thì self cũng giống như con trỏ this vậy. Thực ra ở đây bạn cũng không cần dùng đến self vì chúng ta đang gọi hàm ngay trong chương trình chính chứ không phải bên trong một phương thức hay lớp nào đó.

p Object.class_variables

Cuối cùng là biến class_variables,  biến này lưu trữ toàn bộ biến class có trong chương trình.

[:tree_name]
true
[:@sea_name]
[:@@species]

Biến cục bộ

Biến cục bộ là biến chỉ có hiệu lực trong một phạm vi nhất định trong toàn bộ code Ruby, cụ thể là biến nằm bên trong hàm, phương thức, class.

def method1
   x = 5
   p x    
end

method1 

p x

Trong đoạn code trên chúng ta có phương thức method1 có một biến là x, biến này là biến cục bộ, chúng ta chỉ có thể sử dụng biến này giữa cặp từ khóa def...end.

method1 

Chúng ta gọi phương thức bằng cách ghi rõ tên phương thức ra.

p x

Nếu chúng ta truy xuất biến ở ngoài phạm vi phương thức thì Ruby sẽ báo lỗi NameError vì Ruby không tìm thấy biến đó.

5
./locals.rb:11:in `<main>': undefined local variable 
or method `x' for main:Object (NameError)

Đoạn code dưới đây chỉnh sửa lại từ đoạn code trên một tí.


x = 5

def method1
    x = 10
    p x
end

method1

p x

Trong đoạn code trên chúng ta có 2 biến tên là x, một biến nằm trong phương thức method1 và một biến nằm ở ngoài, mặc dù chúng có cùng tên nhưng đây là 2 biến khác nhau hoàn toàn.

x = 5

Biến x đầu tiên được gán giá trị là 5, biến này có phạm vi trong toàn đoạn code nhưng không thể truy cập ở bên trong phương thức method1.

def method1
    x = 10
    p x
end

Bên trong phươn thức method1 lại có một biến x khác nữa được gán giá trị là 10. Biến này chỉ có hiệu lực bên trong cặp từ khóa def...end.

10
5

Phương thức có thể nhận vào các tham số, các tham số khi truyền vào phương thức sẽ có hiệu lực như một biến cục bộ bên trong phương thức đó:


def rectangle_area a, b
    puts local_variables
    return a * b
end

puts rectangle_area 5, 6

Ở trên chúng ta có phương thức rectangle_area nhận vào 2 tham số ab. Phương thức này tính và trả về diện tích hình chữ nhật.

puts rectangle_area 5, 6

Để truyền tham số vào phương thức thì chúng ta ghi giá trị hoặc biến vào sau lời gọi phương thức.

a
b
30

Một phương thức có thể được định nghĩa bên trong một phương thức khác, phương thức đó gọi là phương thức nội, phương thức nội cũng có biến cục bộ của riêng nó.

def method1
    
    def method2
                
        def method3
            m5, m6 = 3
            puts "Level 3"
            puts local_variables
        end            
        
        m3, m4 = 3
        puts "Level 2"
        puts local_variables
        method3    
    end        
    
    m1, m2 = 3
    puts "Level 1"
    puts local_variables
    method2
            
end

method1

Trong đoạn code trên chúng ta định nghĩa 3 phương thức là method1, method2method3, trong đó method2method3 là các phương thức nội. Phương thức method2 nằm bên trong method1method3 lại nằm bên trong method2. Các biến nằm ở phương thức nào thì chỉ có hiệu lực ở phạm vi phương thức đó.

Level 1
m1
m2
Level 2
m3
m4
Level 3
m5
m6

Biến toàn cục

Biến toàn cục khác biến cục bộ ở chỗ là có hiệu lực trên toàn code. Biến toàn cục có tên bắt đầu bằng ký tự $.


$gb = 6


module ModuleM        
    puts "Inside module"
    puts $gb
end


def method1
    puts "Inside method"
    puts $gb
end


class Some
    puts "Inside class"
    puts $gb
end 

method1

puts "Inside toplevel"
puts $gb
puts global_variables.include? :$gb

Trong đoạn code trên chúng ta có biến toàn cục $gb. Biến toàn cục có thể sử dụng được trong cả module, phương thức, lớp…

$gb = 6

Chúng ta khai báo biến toàn cục $gb và gán giá trị là 6.

module ModuleM        
    puts "Inside module"
    puts $gb
end

Trong module ModuleM chúng ta in giá trị của biến toàn cục.

def method1
    puts "Inside method"
    puts $gb
end

Trong phương thức method1 cũng vậy.

class Some
    puts "Inside class"
    puts $gb
end

Và cả bên trong class cũng vậy.

puts $gb
puts global_variables.include? :$gb

Ở ngoài các phương thức, class… chúng ta cũng có thể gọi đến biến toàn cục $gb.

Inside module
6
Inside class
6
Inside method
6
Inside toplevel
6
true

Ngoài các biến toàn cục do chúng ta định nghĩa, Ruby còn có sẵn các biến được định nghĩa sẵn.

p $LOAD_PATH
p $:

Ở trên chúng ta dùng 2 biến $LOAD_PATH$:, đây đều là các biến lưu trữ thông tin về các đường dẫn thư mục có trong biến môi trường Path của Windows.

Biến instance và biến class

Ở đây chúng ta sẽ tìm hiểu sơ qua về biến instance và biến class. Chúng ta sẽ tìm hiểu thêm trong bài hướng đối tượng.

Biến instance là biến nằm trong một đối tượng cụ thể. Mỗi đối tượng có những biến instance riêng của chúng, biến instance có tên bắt đầu bằng kí tự @.

Biến class là biến nằm trong một lớp. Những đối tượng được tạo ra từ lớp đó sẽ dùng chung biến class, biến class có tên bắt đầu bằng kí tự @@.

class Being
    
    @@is = true
       
    def initialize nm
        @name = nm
    end
    
    def to_s
        "This is #{@name}"
    end    
    
    def does_exist?
        @@is
    end
end

b1 = Being.new "Being 1"
b2 = Being.new "Being 2"
b3 = Being.new "Being 3"

puts b1, b2, b3

p b1.does_exist?
p b2.does_exist?
p b3.does_exist?

Trong đoạn code trên chúng ta định nghĩa lớp Being. Lớp này có một biến instance và một biến class.

class Being
    
    @@is = true

Biến @@is là một biến class, tất cả các đối tượng thuộc lớp Being đều dùng chung một biến @@is.

def initialize nm
    @name = nm
end

Phương thức initialize là phương thức khởi tạo. Phương thức này tự động được gọi khi chúng ta khai báo đối tượng. Mỗi đối tượng thuộc lớp Being có biến instance @name khác nhau.

def to_s
    "This is #{@name}"
end       

Phương thức to_s tự động được gọi khi dùng với hàm như p hay puts. Ở đây phương thức này trả về một chuỗi.

def does_exist?
    @@is
end

Phương thức does_exist? trả về biến class của lớp đó.

b1 = Being.new "Being 1"
b2 = Being.new "Being 2"
b3 = Being.new "Being 3"

Sau khi đã định nghĩa lớp, chúng ta khai báo 3 đối tượng thuộc lớp Beingb1, b2b3. Mỗi đối tượng khi khởi tạo được nhận một tham số dùng cho biến @name của riêng chúng.

puts b1, b2, b3

Phương thức puts sẽ tự động gọi đến phương thức to_s tương ứng với từng đối tượng.

p b1.does_exist?
p b2.does_exist?
p b3.does_exist?

Phương thức does_exist? sẽ trả về giá trị của biến @@is, do cả 3 đối tượng này đều dùng chung biến class @@is nên kết quả trả về là như nhau.

This is Being 1
This is Being 2
This is Being 3
true
true
true






Bình luận (6)

  1. Kiều Thị Ánh

    Em chào ad ạ. Ad cho em hỏi phần biến instance và biến class, em viết code như vậy nhưng lúc chạy nó không ra kết quả ạ.

  2. Kiều Thị Ánh

    Em làm được rồi ạ.Em thay p bằng puts và nó cứ thế in ra ạ… Em và đứa bạn đều không chạy được ạ,. Xong em thử p bằng puts thì nó in ra bình thường ạ.

    1. Phở Code Admin

      Chúc mừng bạn 😀
      Đúng là mình nhầm, hàm p in nội dung của phương thức inspect chứ không phải to_s
      Chỉ có puts mới in ra to_s 🙂
      Mình sửa lại rồi, cám ơn bạn.

Trả lời


Lưu ý: bọc code trong cặp thẻ [code language="x"][/code] để highlight code.


Ví dụ:


[code language="cpp"]


    std::cout << "Hello world";


[/code]



Các ngôn ngữ được hỗ trợ gồm: actionscript3, bash, clojure, coldfusion, cpp, csharp, css, delphi, diff, erlang, fsharp, go, groovy, html, java, javafx, javascript, latex, matlab, objc, perl, php, powershell, python, r, ruby, scala, sql, text, vb, xml.

Thư điện tử của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *