Category Archives: Ruby – Lập trình Ruby

Ruby – Kiểu dữ liệu – Phần 2

Trong phần này chúng ta tiếp tục tìm hiểu về các kiểu dữ liệu của Ruby.

Số hữu tỉ – Rational

Số hữu tỉ là số có thể biểu diễn dưới dạng phân số. Sử dụng số hữu tỉ sẽ giúp tránh các lỗi về làm tròn số vì chúng ta có thể biểu diễn chúng dưới dạng phân số. Ruby có lớp Rational hỗ trợ làm việc với số hữu tỉ. Một số đối tượng trong Ruby có phương thức to_r để chuyển một số thành số hữu tỉ.

puts 5.to_r
puts "43".to_r
puts 1.5.to_r

p Rational 0
p Rational 2/5.0
p Rational 1.5

Trong đoạn code trên chúng ta thực hiện một số thao tác với số hữu tỉ.

puts 5.to_r

Chúng ta có thể chuyển số nguyên 5 sang 5/1 bằng phương thức to_r.

p Rational 1.5

Hoặc chúng ta có thể tạo ra từ lớp Rational.

5/1
43/1
3/2
(0/1)
(3602879701896397/9007199254740992)
(3/2)

Đối tượng nil

Trong C++, Java… có đối tượng NULL thì trong Ruby chúng được gọi là nil. Đây là một đối tượng mô tả giá trị “không có”, ý nói một biến không có giá trị gì cả. nil là một đối tượng tĩnh, tức là trong Ruby chỉ có một đối tượng nil duy nhất giống như đối tượng true hay false vậy, nil được tạo ra từ lớp NilClass.

puts nil
p nil

p $val

p $val1 == $val2

Đoạn code trên thực hiện một số thao tác với nil.

puts nil
p nil

Phương thức puts sẽ in chuỗi rỗng của đối tượng nil, trong khi phương thức p lại in chuỗi "nil" ra màn hình.

p $val

Nếu chúng ta in một biến chưa có giá trị thì Ruby sẽ hiển thị là nil.

p $val1 == $val2

Dòng code trên sẽ trả về true vì đối tượng nil là một đối tượng tĩnh và nó chỉ có 1.


nil
nil
true

Kiểu chuỗi – String

Một string là một dãy các kí tự liên tiếp nhau. Trong Ruby chúng là các đối tượng thuộc lớp String. Các chuỗi string được bọc trong cặp dấu nháy đơn hoặc nháy kép.

String là một kiểu dữ liệu quan trọng, trong phần sau chúng ta sẽ tìm hiểu kĩ hơn về kiểu dữ liệu này.

p "Hello"
p 'Ruby'

p "Ruby".size
p "Ruby".upcase

p 2.to_s

Trong đoạn code trên chúng ta in một số string và các tính chất của chúng ra màn hình.

p "Hello"
p 'Ruby'

String có thể được bọc trong cặp dấu nháy đơn hoặc nháy kép.

p "Ruby".size
p "Ruby".upcase

Ở 2 dòng trên chúng ta gọi đến phương thức size và phương thức upcase, phương thức size trả về độ lớn của string còn phương thức upcase chuyển một string thành dạng chữ in hoa.

p 2.to_s

Trong dòng trên phương thức to_s chuyển một số thành một string.

"Hello"
"Ruby"
4
"RUBY"
"2"

Mảng và bảng băm

Mảng và bảng băm lưu dữ liệu theo dạng tập hợp, tức là chúng không lưu từng giá trị cụ thể mà lưu một nhóm các phần tử có giá trị khác nhau.

Mảng lưu các phần tử theo một thứ tự trong khi bảng băm lưu phần tử theo các cặp khóa-giá trị. Chúng ta sẽ tìm hiểu thêm về 2 kiểu dữ liệu này trong các bài sau.

nums = [1, 2, 3, 4]

puts "There are #{nums.size} items in the array"

nums.each do |num|
    puts num
end


domains = { :de => "Germany", :sk => "Slovakia",
            :us => "United States", :no => "Norway" }

puts domains.keys
puts domains.values

Đoạn code trên ví dụ về mảng và bảng băm trong Ruby.

nums = [1, 2, 3, 4]

puts "There are #{nums.size} items in the array"

nums.each do |num|
    puts num
end

Trong đoạn code trên, dòng đầu tiên tạo một mảng có 4 phần tử. Dòng thứ hai sẽ in số lượng phần tử trong mảng ra màn hình. Các dòng sau duyệt qua mảng để lấy từng phần tử của mảng và in ra màn hình.

domains = { :de => "Germany", :sk => "Slovakia",
            :us => "United States", :no => "Norway" }

puts domains.keys
puts domains.values

Ở đây chúng ta tạo một đối tượng bảng băm và in danh sách khóa và giá trị ra màn hình.

There are 4 items in the array
1
2
3
4
de
sk
us
no
Germany
Slovakia
United States
Norway

Chuyển đổi kiểu dữ liệu

Ruby có các phương thức hỗ trợ chuyển đổi kiểu dữ liệu như to_i, to_s hay to_f. Ngoài trong module Kernel còn có các phương thức như Integer, String hoặc Float cũng làm công việc tương tự.

p Array(1..6)
p Complex 6
p Float 12
p Integer "34"
p Rational 6
p String 22

Đoạn code trên chuyển đổi kiểu dữ liệu bằng các phương thức của module Kernel.

[1, 2, 3, 4, 5, 6]
(6+0i)
12.0
34
(6/1)
"22"

Đoạn code dưới đây chuyển đổi đối tượng sang kiểu số nguyên và số chấm động.

p "12".to_i
p 12.5.to_i
p nil.to_i

p 12.to_f
p "11".to_f
p nil.to_f

Một số đối tượng trong Ruby chứa phương thức to_ito_f giúp chuyển đổi sang kiểu số nguyên và số chấm động tương ứng.

12
12
0
12.0
11.0
0.0

Chúng ta có thể chuyển một string sang khá nhiều kiểu dữ liệu khác nhau:

p "12".to_i
p "13".to_f
p "12".to_r
p "13".to_c

p "Jane".to_sym

v = "Ruby Python Tcl PHP Perl".split
p v.class

Trong đoạn code trên chúng ta chuyển string sang số nguyên, số thực, số hữu tỉ, số phức, mảng và thậm chí là thành một symbol.

v = "Ruby Python Tcl PHP Perl".split
p v.class

Phương thức split sẽ tách từng kí tự trong string và lưu trong một mảng.

12
13.0
(12/1)
(13+0i)
:Jane
Array

Ruby – Kiểu dữ liệu – Phần 1

Trong phần này chúng ta sẽ tìm hiểu về các kiểu dữ liệu.

Tất cả các chương trình máy tính trên thế giới đều sử dụng dữ liệu, từ trình soạn thảo văn bản, máy tính, game… dữ liệu cũng được chia làm nhiều loại khác nhau chẳng hạn như số, kí tự, hình ảnh, âm thanh… Kiểu dữ liệu là một tập các giá trị và các thao tác có thể có trên các giá trị đó.

Tất cả các kiểu dữ liệu trong Ruby đều là lớp. Ruby hỗ trợ một số kiểu dữ liệu cơ bản sau đây:

  • Boolean – kiểu luận lý
  • Symbol
  • Number – số
  • String – chuỗi kí tự
  • Array – mảng
  • Hashe – bảng băm

Ví dụ:

h = { :name => "Jane", :age => 17 }

p true.class, false.class
p "Ruby".class
p 1.class
p 4.5.class
p 3_463_456_457.class
p :age.class
p [1, 2, 3].class
p h.class

Trong đoạn code trên chúng ta in tên lớp của từng kiểu dữ liệu khác nhau.

p true.class, false.class

Kiểu boolean có 2 giá trị là True hoặc False.

p "Ruby".class

Kiểu string, chúng ta đã làm việc với kiểu này trong các bài trước.

p 1.class
p 4.5.class
p 3_463_456_457.class

Kiểu số, gồm số nguyên và số thực.

p :age.class

Kiểu Symbol.

p [1, 2, 3].class
p h.class

Ở đây chúng ta có một đối tượng mảng và một đối tượng bảng băm.

TrueClass
FalseClass
String
Fixnum
Float
Bignum
Symbol
Array
Hash

Kiểu Boolean

Nói một cách “triết lý” thì trên thế giới này có một số thứ tồn tại theo 2 trạng thái/thái cực khác nhau… chẳng hạn như có Thiên đàng và Địa ngục, Nước và Lửa, Nam và Nữ… kiểu dữ liệu boolean cũng vậy, đối tượng thuộc kiểu này có một trong 2 trạng thái là True (đúng) hoặc False (sai). Đây là một kiểu dữ liệu quan trọng mà hầu hết ngôn ngữ lập trình nào cũng có.

Ví dụ:

bool = [true, false]

male = bool[rand(2)]


if male
    puts "We will use name John"
else 
    puts "We will use name Victoria"
end

Trong đoạn code trên chúng ta sử dụng phương thức rand() để lấy giá trị ngẫu nhiên từ 0→1.

bool = [true, false]

Chúng ta có một biến tên là bool, đây là một mảng có 2 giá trị là true hoặc false. Một mảng được tạo bằng cách sử dụng cặp dấu [].

male = bool[rand(2)]

Khi phương thức rand() trả về 0 hoặc 1, chúng ta dùng kết quả đó để lấy giá trị tương ứng trong mảng bool, tức là nếu 0 thì biến male có giá tri là true, nếu 1 thì malefalse.

if male
    puts "We will use name John"
else 
    puts "We will use name Victoria"
end

Tùy vào giá trị của male mà chúng ta in ra câu lệnh tương ứng với từ khóa if..else..end.

We will use name Victoria

Kiểu Symbol

Nếu bạn biết kiểu enum trong C++, Java… thì trong Ruby chúng được gọi là Symbol. Symbol được dùng để biểu diễn các đối tượng khác. Dùng symbol sẽ tiết kiệm được nhiều tài nguyên hơn so với dùng biến thông thường. Tất cả các biến symbol đều là một đối tượng từ lớp Symbol. Để định nghĩa một symbol thì chúng ta thêm dấu hai chấm ":" vào trước giá trị, ví dụ :name. Hầu hết các đối tượng trong Ruby đều có phương thức to_sym để chuyển một đối tượng thành một symbol.

Symbol không thể thay đổi được giá trị. Thường thì symbol được dùng để làm khóa trong bảng băm.

p :name
p :name.class
p :name.methods.size
p "Jane".methods.size

p :name.object_id
p :name.object_id
p "name".object_id
p "name".object_id

Trong đoạn code trên chúng ta thực hiện một số thao tác với symbol.

p :name
p :name.class

Chúng ta in symbol và tên của chúng ra màn hình.

p :name.methods.size
p "Jane".methods.size

Chúng ta so sánh kích thước dữ liệu của một symbol và một string. Rõ ràng là một string có kích thước lớn hơn một symbol.

p :name.object_id
p :name.object_id
p "name".object_id
p "name".object_id

Symbol giống nhau thì có id giống nhau, string giống nhau thì lại có id khác nhau.

:name
Symbol
79
162
10328
10328
77344750
77344730

Ngoài ra Symbol cũng thường được dùng để dánh dấu, chẳng hạn như thay vì khai báo biến number = 1 rồi thực hiện if number == 1... thì ở đây chúng ta dùng symbol sẽ tiết kiệm được bộ nhớ cũng như dễ code hơn.

light = :on

if light == :on
    puts "The light is on"
else
    puts "The light is off"
end

light = :off

if light == :on
    puts "The light is on"
else
    puts "The light is off"
end

Trong đoạn code trên chúng ta in các đoạn text khác nhau tùy theo giá trị của biến light.

Symbol còn được dùng để làm khóa trong bảng băm.

domains = {:sk => "Slovakia", :no => "Norway", :hu => "Hungary"}

puts domains[:sk]
puts domains[:no]
puts domains[:hu]

Trong đoạn code trên chúng ta có một đối tượng bảng băm là domains, đối tượng này dùng khóa là các Symbol.

puts domains[:sk]
puts domains[:no]
puts domains[:hu]

Chúng ta lấy giá trị của từng phần tử trong bảng băm bằng khóa.

Slovakia
Norway
Hungary

Kiểu số nguyên – Integer

Trong lập trình thì thì integer là một kiểu dữ liệu cơ bản, mặc dù trong toán thì số nguyên là  tập hợp Z, một tập hợp vô hạn, nhưng trong máy tính thì không có cái gì vô hạn cả, chúng ta có thể có tập hợp các số nguyên nhưng tập hợp này chỉ trong một phạm vi nhất định.

Trong Ruby thì số nguyên là các đối tượng thuộc lớp Fixnum hoặc Bignum, 2 lớp này có độ lớn khác nhau, độ lớn là khoảng giá trị của một đối tượng, ví dụ như trong C++, Java thì một số nguyên thường có độ lớn từ -2^32 đến 2^32, trong Ruby thì độ lớn của Fixnum tùy thuộc vào hệ điều hành, nếu một số nguyên có giá trị lớn hơn ngưỡng cho phép thì sẽ tự động được chuyển thành kiểu Bignum nên chúng ta cũng không cần phải quan tâm lắm đến vấn đề này.

p -2
p 121
p 123265
p -34253464356
p 34867367893463476

p 1.class
p 23453246.class
p 234532423563456346.class
p 2345324235632363463456456346.class

p 5 / 2
p 5.div 2

Đoạn code trên thực hiện một số thao tác với số nguyên.

p -2
p 121
p 123265
p -34253464356
p 34867367893463476

Trên đây là các con số cả âm lẫn không âm với các độ lớn khác nhau.

p 1.class
p 23453246.class
p 234532423563456346.class
p 2345324235632363463456456346.class

Chúng ta in ra tên lớp của các số nguyên. Hai số đầu tiên có kiểu Fixnum trong khi 2 số sau có kiểu Bignum.

p 5 / 2
p 5.div 2

Chúng ta thực hiện phép chia 2 số nguyên bằng toán tử / và phương thức div. Phép chia một số nguyên cũng sẽ trả về một số nguyên.

-2
121
123265
-34253464356
34867367893463476
Fixnum
Fixnum
Bignum
Bignum
2
2

Số nguyên còn có thể được biểu diễn trong nhiều hệ cơ số khác nhau như hệ thập phân (10), hệ thập lục phân (16), hệ bát phân (8), và hệ nhị phân (2). Hệ thập phân là hệ cơ số mà chúng ta thường dùng nhất, hệ thập lục phân được biểu diễn với kí tự 0x ở đầu, hệ bát phân dùng kí tự 0 và hệ nhị phân dùng kí tự 0b.

puts 122
puts 0x7a
puts 0172
puts 0b1111010

Đoạn code trên in số 122 ở bốn hệ cơ số khác nhau.

122
122
122
122

Bignum hay “số nguyên lớn” là các con số có số lượng chữ số rất lớn, thường là vài trăm chữ số, đọc số nguyên lớn cũng rất khó chịu, chẳng hạn như số 936758346345906394… do đó Ruby cho phép số nguyên lớn có thể có dấu gạch dưới “_” để chúng ta dễ đọc hơn, khi dịch thì trình thông dịch Ruby sẽ bỏ qua các dấu gạch dưới đó.

p 23482345629
p 23_482_345_629

p 23482345629 == 23_482_345_629

Đoạn code trên sử dụng dấu gạch dưới cho số nguyên lớn.

23482345629
23482345629
true

Số chấm động

Số chấm động tức là số thực, số thực thường được dùng để đo các giá trị liên tục như trọng lượng, tốc độ, chiều dài… Trong Ruby thì số thực được biểu diễn bởi lớp Float hoặc BigDecimal.

p 15.4
p 0.3455
p -343.4563

p 12.5.class
p -12.5.class
p (5.0 / 2).class

p 5.fdiv 2
p 12.to_f

Đoạn code trên thực hiện một số thao tác với số chấm động.

p 15.4
p 0.3455
p -343.4563

Chúng ta in 3 số chấm động, số chấm động có phần thập phân nằm phía sau dấu chấm.

p 12.5.class
p -12.5.class
p (5.0 / 2).class

Chúng ta in tên lớp biểu diễn số chấm động. Ngoài ra nếu chúng ta thực hiện tính toán một số nguyên với một số chấm động thì kết quả sẽ cho ra một số chấm động.

p 5.fdiv 2
p 12.to_f

Chúng ta tạo các số chấm động bằng phương thức fdiv và phương thức to_f. Phương thức fdiv chẳng qua là thực hiện phép chia nhưng trả về số chấm động mặc dù phép chia đó thực hiện trên 2 số nguyên, còn phương thức to_f sẽ chuyển đổi một số bất kì thành số thực.

15.4
0.3455
-343.4563
Float
Float
Float
2.5
12.0

Mặc định thì phần thập phân chỉ hiển thị tối đa 16 chữ số nhưng chúng ta có thể định dạng kiểu hiển thị theo ý chúng ta với phương thức sprintf hoặc printf.

p 1/3.0
p 1.fdiv 2

puts sprintf "%.4f" % (1/3.0)
puts sprintf "%.7f" % (5/3.0)

Đoạn code trên sẽ định dạng hiển thị số chấm động.

p 1/3.0
p 13.fdiv 4
p 1.fdiv 2

Phương thức p sẽ in các số chấm động một cách mặc định.

puts sprintf "%.4f" % (1/3.0)
puts sprintf "%.7f" % (5/3.0)

Chúng ta định dạng lại số chấm động bằng phương thức sprintf, phương thức này nhận vào một chuỗi định dạng, chuỗi này có dạng %... ở đây %.4f tức là hiển thị 4 chữ số phía sau dấu chấm, tương tự %.7f là hiển thị 7 chữ số, kí tự f cho Ruby biết kiểu định dạng này được sử dụng với số chấm động.

0.3333333333333333
3.25
0.5
0.3333
1.6666667

 

Ruby – Đối tượng

Trong phần này chúng ta sẽ tìm hiểu sơ qua về đối tượng trong Ruby, các bài sau sẽ trình bày chi tiết hơn.

Ruby là một ngôn ngữ lập trình hướng đối tượng. Tất cả mọi thứ trong Ruby đều là đối tượng. Các đối tượng trong Ruby tồn tại trong suốt quá trình biên dịch code. Có 2 loại đối tượng là đối tượng có sẵn và đối tượng do chúng ta định nghĩa. Đối tượng có sẵn là các đối tượng đã được định nghĩa sẵn trong Ruby hoặc các thư viện do người khác viết bằng Ruby và chúng ta có thể sử dụng. Còn loại kia là đối tượng do chúng ta định nghĩa để sử dụng với công việc đặc thù của riêng chúng ta khi các đối tượng có sẵn không đáp ứng được.

Muốn sử dụng đối tượng thì chúng ta phải khởi tạo trước. Một đối tượng chứa thuộc tính và phương thức bên trong nó. Thuộc tính là dữ liệu của đối tượng, đây là thành phần tĩnh, phương thức là phần động. Đối tượng có thể được chỉnh sửa hoặc giao tiếp với các đối tượng khác thông qua phương thức.

puts "Ruby language"

Nếu bạn đã từng lập trình C++, Java thì bạn cũng đã biết tới những từ khóa hoặc hàm dùng để in một chuỗi ra màn hìnhchẳng hạn như hàm printf() trong C, std::cout trong C++, System.out.println() trong Java… các hàm này có chức năng là in một chuỗi ra màn hình, từ khóa puts trong Ruby ở trên cũng có chức năng tương tự. Các từ khóa/hàm này nhận vào một giá trị là một chuỗi, trong ví dụ trên thì “Ruby language” là một giá trị,

Nhưng trong Ruby thì có hơi khác, bản thân chuỗi “Ruby language” cũng là một đối tượng. Do đó chúng ta cũng có thể gọi phương thức từ chuỗi này.

Ngoài ra phương thức tồn tại trong các đối tượng chứ không tự tồn tại một mình ở đâu đó được, puts cũng là một phương thức của một đối tượng đó là module Kernel.

Ví dụ 1:

Kernel.puts "Ruby language"
Kernel.puts "Ruby language".size

Trong dòng code đầu tiên chúng ta gọi phương thức puts và gọi cả tên module Kernel ra luôn. Trong C# hay Java cũng tương tự là Console.writelnSystem.out.println(). Tất nhiên là chúng ta cũng không cần gọi Kernel ra như vậy trong Ruby nhưng ví dụ này chỉ để khẳng định là phương thức thì luôn đi kèm với một đối tượng nào đó.

Trong dòng tiếp theo chúng ta in ra kích thước của chuỗi “Ruby language”, điều này chứng tỏ chuỗi “Ruby language” cũng chính là một đối tượng chứ không đơn thuần chỉ là một giá trị như trong các ngôn ngữ khác. Phương thức size sẽ trả về số lượng kí tự trong một chuỗi.

Ruby language
13

Ví dụ 2:


puts 6.object_id

puts 6.even?
puts 6.zero?

puts 6.class

Chúng ta có số 6 và cũng có thể gọi một số phương thức của số 6 này.

puts 6.object_id

Mỗi đối tượng đều được gán một id và chúng ta có thể lấy giá trị đó ra bằng cách gọi phương thức object_id. Mỗi lời gọi phương thức đều được đặt sau dấu chấm sau tên đối tượng.

puts 6.even?
puts 6.zero?

Phương thức even? trả về True nếu số đó là số chẵn và ngược lại. Phương thức zero? trả về True nếu số đó là 0. Ở đây có một điểm lưu ý là nếu phương thức trả về True hoặc False thì phải kèm thêm dấu ? sau tên phương thức.

puts 6.class

Phương thức class cho biết tên lớp của đối tượng, ở đây số 6 là một đối tượng thuộc lớp Fixnum.

13
true
false
Fixnum

Tạo đối tượng

Một đối tượng phải được tạo ra thì mới có thể sử dụng được. Đối tượng trong Ruby có thể được tạo ra một cách rõ ràng hoặc tạo ngầm. Ví dụ về đối tượng ngầm là mấy cái đối tượng được tạo ra từ giá trị như số 6 hay chuỗi “Ruby language” ở trên. Còn để tạo đối tượng một cách rõ ràng thì chúng ta dùng từ khóa new. Đối tượng thuộc lớp do chúng ta tự định nhĩa cũng dùng từ khóa new.


class Being
end
    
puts 67
puts "Hello world"

s = String.new "Hello world"
puts s

# n1 = Fixnum.new 67
# puts n1

b = Being.new
puts b

Trong đoạn code trên chúng ta tạo một số đối tượng bằng các cách khác nhau.

class Being
end

Chúng ta định nghĩa lớp Being. Để định nghĩa một lớp thì chúng ta dùng từ khóa class.

puts 67
puts "Hello world"

Hai dòng code trên tạo đối tượng ngầm là 67 và chuỗi “Hello world”.

s = String.new "Hello world"
puts s

Tương tự, chúng ta có thể tạo đối tượng string một cách rõ ràng luôn với từ khóa new.

# n1 = Fixnum.new 67
# puts n1

Không phải tất cả các lớp có sẵn trong Ruby đều có thể được tạo ra bằng từ khóa new, Fixnum là một ví dụ, các đối tượng Fixnum chỉ có thể được tạo ngầm.

b = Being.new
puts b

Đoạn code trên tạo đối tượng b từ lớp Being do chúng ta định nghĩa.

67
Hello world
Hello world
#<Being:0x8492o3a>

Đối tượng giá trị

Như đã nói ở trên là chúng ta có thể tạo đối tượng một cách ngầm định từ các giá trị. Ở đây chúng ta sẽ làm việc với một số phương thức của loại đối tượng này.

4.times { puts "Ruby" }

puts "Ruby".size
puts "Ruby".downcase

puts [1, 2, 3].include? 3
puts [1, 2, 3].empty?

puts :name.class
puts :name.frozen?

puts (1..6).class
puts (1..6).include? 4

Trong đoạn code trên chúng ta có các đối tượng Fixnum, String, Array, kiểu Symbol và kiểu Range. Chúng ta sẽ tìm hiểu kỹ hơn về các kiểu đối tượng này trong bài sau.

4.times { puts "Ruby" }

Phương thức times của đối tượng Fixnum thực hiện phép nhân lên giá trị phía sau nó, ở đây là thực hiện puts "Ruby" 4 lần.

puts "Ruby".size
puts "Ruby".downcase

Phương thức size lấy về số kí tự trong chuỗi, phương thức downcase thực hiện chuyển chuỗi về kiểu chữ in thường.

puts [1, 2, 3].include? 3
puts [1, 2, 3].empty?

Trong 2 dòng code trên chúng ta sử dụng đối tượng kiểu mảng – Array, phương thức include? cho biết một giá trị nào đó có thuộc mảng hay không. Phương thức empty? cho biết mảng này rỗng hay không.

puts :name.class
puts :name.frozen?

Ở 2 dòng trên chúng ta thao tác với kiểu Symbol, symbol có tên bắt đầu bằng dấu 2 chấm ":" chúng ta sẽ tìm hiểu thêm trong bài sau.

puts (1..6).class
puts (1..6).include? 4

Cuối cùng là 2 đối tượng kiểu Range, về bản chất thì kiểu này cũng tương tự như kiểu mảng vậy. Phương thức class trả về tên của kiểu dữ liệu này, còn phương thức include? cho biết giá trị nào đó có nằm trong danh sách hay không.

Ruby
Ruby
Ruby
Ruby
4
ruby
true
false
Symbol
false
Range
true

Thừa kế

Một trong những khái niệm trong lập trình hướng đối tượng là thừa kế và Ruby cũng thế. Thừa kế bao gồm các đối tượng cha và đối tượng con, đối tượng cha sẽ chứa những thuộc tính và phương thức mà đối tượng con có thể thừa kế lại. Tất cả các đối tượng trong Ruby đều thừa kế từ một đối tượng gốc có tên là Object. Tất cả các đối tượng trong Ruby đều có các phương thức mà đối tượng Object có, nhưng có thể định nghĩa lại.

puts 4.is_a? Object
puts "Ruby".is_a? Object
puts [2, 3].is_a? Object
puts :name.is_a? Object
puts (1..2).is_a? Object

Đoạn code trên cho chúng ta thấy tất cả các đối tượng đều thừa kế từ đối tượng Object.

puts 4.is_a? Object

Trong dòng code trên phương thức is_a? cho biết đối tượng 4 có được kế thừa từ đối tượng Object hay không.

true
true
true
true
true

Trong ví dụ dưới đây, chúng ta sẽ định nghĩa các lớp có kế thừa nhau.

class Being

    def to_s
        "This is Being"
    end
    
    def get_id
        9
    end
end

class Living < Being
    
    def to_s
        "This is Living"
    end
end

l = Living.new

puts l
puts l.get_id
puts l.is_a? Being

Chúng ta định nghĩa 2 lớp BeingLiving, lớp Living kế thừa từ lớp Being, do đó lớp Being là lớp cha, lớp Living là lớp con.

class Being

    def to_s
        "This is Being"
    end
    
    def get_id
        9
    end
end

Để định nghĩa một lớp thì chúng ta sử dụng cặp từ khóa class...end, sau từ khóa class là tên lớp mà chúng ta muốn đặt. Bên trong lớp chúng ta có thể định nghĩa các phương thức bằng cách dùng cặp từ khóa def…end, sau từ khóa def cũng từ tên phương thức mà chúng ta muốn đặt. Trong đoạn code trên chúng ta có 2 phương thức là to_sget_id.

Đối tượng nào cũng có phương thức to_s cả vì mặc định đối tượng Object cũng có phương thức này. Khi chúng ta dùng phương thức puts để in ra một giá trị nào đó thì phương thức này sẽ tự động gọi đến phương thức to_s có trong các đối tượng. Trong ví dụ này chúng ta định nghĩa lại phương thức to_s, nếu không thì puts sẽ sử dụng phương thức to_s mặc định của đối tượng Object.

class Living < Being
    
    def to_s
        "This is Living"
    end
end

Chúng ta định nghĩa lớp Living, lớp này kế thừa từ lớp Being, để một lớp được kế thừa từ lớp khác thì chúng ta thêm dấu < cùng với tên của lớp cha vào sau tên lớp con. Ở đây lớp Living cũng định nghĩa lại phương thức to_s của riêng nó.

l = Living.new

Chúng ta tạo đối tượng Living bằng cách dùng từ khóa new.

puts l

Phương thức puts sẽ gọi đến phương thức to_s trong lớp Living.

puts l.get_id

Lớp Living không định nghĩa lại phương thức get_id nên Ruby sẽ tìm dần dần các lớp cha xem lớp nào có thì gọi phương thức get_id từ lớp đó.

puts l.is_a? Being

Dòng code trên sẽ trả về True vì lớp Living kế thừa từ lớp Being nên một đối tượng Living cũng là một đối tượng Being.

This is Living
9
true

Đối tượng main

Trong các ngôn ngữ như C++, Java… thì chương trình bắt đầu chạy từ một hàm đặc biệt tên là hàm main(), khi chạy chương trình hàm này sẽ được gọi từ hệ điều hành.

Trong Ruby cũng thế, mỗi đoạn code trong file .rb đều nằm trong một đối tượng có tên là main mặc dù ở đây chúng ta không khai báo ra, đối tượng này cũng kế thừa từ đối tượng Object. Chính vì main cũng là một đối tượng nên các biến được khai báo trong main cũng là thuộc tính của main.

n1 = 3
n2 = 5

puts local_variables

Kernel.puts self
puts self.class

Đoạn code trên ví dụ về đối tượng main trong Ruby.

n1 = 3
n2 = 5

Chúng ta có 2 đối tượng số nguyên. Cả hai đối tượng này đều thuộc về đối tượng main.

puts local_variables

Biến local_variables thực chất là một phương thức của module Kernel, lưu trữ danh sách các biến cục bộ hiện có.

Kernel.puts self

Biến self là biến tham chiếu đến đối tượng hiện tại, nói cho dễ hiểu thì self chính là main, nếu bạn biết con trỏ this trong C++, Java… thì self cũng giống như con trỏ this vậy.

puts self.class

Biến class cho biết tên lớp của đối tượng hiện tại, hiện tại chúng ta dùng đối tượng self (hoặc main) mà đây là đối tượng thuộc lớp Object nên dòng trên sẽ in ra chuỗi Object.

n1
n2
main
Object

 

Ruby – Biến

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

Ruby – Cơ bản

Trong phần này chúng ta sẽ học cách làm việc với ngôn ngữ Ruby.

Ví dụ một đoạn code Ruby:

puts "This is Ruby"

Đoạn code trên rất đơn giản, chỉ là in chuỗi “This is Ruby” ra màn hình console. Từ khóa puts nhận vào một tham số phía sau nó là một chuỗi text, chuỗi text được bọc trong cặp dấu nháy kép "".

This is Ruby

Đọc dữ liệu vào từ terminal (trong Windows là Command Promptcmd):

print "What is your name? "
name = gets

puts "Hello #{name}"

Đoạn code trên sẽ nhận một chuỗi do chúng ta nhập vào từ bàn phím rồi in ra màn hình.

print "What is your name? "

Từ khóa print cũng có tác dụng in một chuỗi text lên màn hình nhưng không xuống dòng như từ khóa puts.

name = gets

Dòng code trên sẽ đọc một đoạn text từ người dùng và lưu vào biến name bằng cách sử dụng phương thức gets,

puts "Hello #{name}"

#{name} sẽ thay bằng giá trị của biến name, bằng cách đó chúng ta có thể đưa giá trị của biến vào trong chuỗi.

What is your name? Pho Code
Hello Pho Code

Ngoài cách chạy code Ruby từ file script thì chúng ta cũng có thể chạy code từng dòng trong terminal:

C:\User\PhoCode>ruby -e "puts RUBY_VERSION"
2.2.4

Khi chúng ta chạy code Ruby từ file script, chẳng hạn như ruby hello.rb thì trình thông dịch Ruby sẽ đọc và dịch code trong file hello.rb, còn nếu chúng ta đưa vào tham số -e thì Ruby sẽ thực thi đoạn lệnh phía sau chứ không tìm file để chạy.

Ngoài ra trình thông dịch Ruby còn có tham số -c, khi dùng tham số này thì trình thông dịch Ruby sẽ thực hiện kiểm tra lỗi cú pháp của đoạn code chứ không thực hiện đoạn code bên trong, nếu không có lỗi thì sẽ in đoạn text “Syntax OK” ra màn hình.

puts "This is Ruby

Đoạn có trên có lỗi cú pháp là thiếu dấu " kết thúc chuỗi.

C:\User\PhoCode>ruby -c syntax_check.rb 
syntax_check.rb:1: unterminated string meets end of file

Trình thông dịch sẽ báo lỗi nếu có lỗi.

Đưa tham số vào chương trình

Khi chúng ta chạy một file script Ruby thì có thể đưa các tham số vào chương trình để sử dụng.

puts ARGV

Trong Ruby biến toàn cục ARGV là biến lưu các tham số được truyền vào chương trình, đây là một mảng, mỗi phần tử trong mảng là một tham số.

puts ARGV

Chúng ta in toàn bộ tham số được đưa vào chương trình.

C:\User\PhoCode>ruby args.rb 1 2 3
1
2
3

Chúng ta truyền tham số vào bằng cách gõ các giá trị vào sau tên file script. Trong đoạn code trên chúng ta truyền vào 3 con số.

Ngoài ra chúng ta có thể lấy từng tham số đơn lẻ:

puts $0
puts $*

Trong Ruby các biến toàn cục có tên bắt đầu bằng kí tự $ theo sau là tên biến. Ngoài ra Ruby còn có sẵn một số biến đặc biệt, chẳng hạn như $0 lưu tên file script được thực thi, $* cũng lưu các tham số truyền vào như ARGV.

C:\User\PhoCode>ruby args2.rb Ruby Python Perl
Ruby
Python
Perl

Biến và hằng số

Biến là nơi để lưu trữ dữ liệu. Biến gồm có tên và kiểu dữ liệu, kiểu dữ liệu là các loại giá trị khác nhau, ví dụ như số nguyên, chuỗi, số thực… là các loại kiểu dữ liệu khác nhau. Không giống các ngôn ngữ như C++, Java… bạn phải khai báo rõ ràng kiểu dữ liệu cùng tên biến như int a, Ruby là ngôn ngữ động, tức là bạn chỉ cần khai báo tên biến và gán giá trị cho nó là Ruby sẽ tự quy định kiểu dữ liệu, ngoài ra bạn cũng có thể thay đổi giá trị và Ruby cũng sẽ tự động thay đổi kiểu dữ liệu cho bạn luôn.

Hằng số trong Ruby cũng khác với các ngôn ngữ khác, trong các ngôn ngữ như C++, Java… thì hằng số là không thể thay đổi được giá trị, còn hằng số trong Ruby thì có thể thay đổi được, khi dịch thì Ruby không báo lỗi mà chỉ đưa ra các lời cảnh báo.

city = "New York"
name = "Paul"; age = 35
nationality = "American"

puts city
puts name
puts age
puts nationality

city = "London"

puts city

Trong đoạn code trên chúng ta làm việc với 4 biến.

city = "New York"

Biến city lưu trữ một chuỗi text, Ruby tự động nhận diện kiểu dữ liệu.

name = "Paul"; age = 35

Khi khai báo nhiều biến trên cùng một dòng thì chúng ta phải ngăn cách chúng bằng dấu chấm phẩy. Trong thực tế thì tốt hơn hết là chúng ta khai báo trên nhiều dòng khác nhau.

puts city
puts name
puts age
puts nationality

Chúng ta in các biến ra màn hình

city = "London"

Đoạn code trên sẽ gán lại giá trị mới cho biến city.

C:\User\PhoCode>ruby variables.rb 
New York
Paul
35
American
London

Trong đoạn code dưới đây chúng ta sẽ làm việc với hằng số.

WIDTH = 100
HEIGHT = 150

var = 40
puts var

var = 50
puts var

puts WIDTH
WIDTH = 110
puts WIDTH

Chúng ta khai báo 2 hằng và một biến.

WIDTH = 100
HEIGHT = 150

Chúng ta chỉ cần đặt tên với chữ cái đầu viết hoa thì biến đó sẽ là hằng số. Trong thực tế thì chúng ta nên viết hoa toàn bộ các chữ cái trong tên hằng.

C:\User\PhoCode>ruby constants.rb 
40
50
100
constants.rb:13: warning: already initialized constant WIDTH
110

Ruby – Các thành phần của Ruby

Một ngôn ngữ lập trình bao gồm nhiều thành phần cấu thành nên nó. Trong phần này chúng ta sẽ tìm hiểu các thành phần cấu tạo nên ngôn ngữ lập trình Ruby.

Bình luận – Comment

Các đoạn comment được dùng để ghi chú mã nguồn. Cú pháp comment của Ruby có 2 loại là comment cho một dòng và comment cho nhiều dòng. Comment trên một dòng được bắt đầu bởi dấu #, comment trên nhiều dòng được bọc bởi cặp kí hiệu =begin=end.

=begin
  comments.rb
  Pho Code
=end

puts "Comments example"

Các dòng comment sẽ không được dịch bởi trình thông dịch.

=begin
  comments.rb
  Pho Code
=end

Biến – Variable

Biến chỉ là một cái tên, đại diện cho một thứ gì đó có công việc là lưu trữ một giá trị nào đó. Trong lập trình thì chúng ta nói là “gán giá trị cho biến”, giá trị ở đây có thể là một đoạn text, một con số hay một đối tượng nào đó.

Tên của các biến được đặt bằng các kí tự trong bảng chữ cái và dấu gạch dưới, nhưng không được bắt đầu bằng kí tự số, cũng không được bắt đầu bằng kí tự viết HOA, nếu dùng chữ HOA thì Ruby sẽ gọi đây là “hằng số”.

Value
value2
company_name

Value là một hằng số, value2company_name là biến.

12Val
exx$
first-name

Ở trên là các tên biến không hợp lệ.

Tên biến có thể được bắt đầu bởi 2 kí tự đặc biệt là @$chúng ta sẽ tìm hiểu thêm sau.

Biến trong Ruby là có phân biệt HOA-thường, tức là pricepRice là 2 biến khác nhau.

Hằng số – Constant

Trong các ngôn ngữ khác thì hằng số cũng là các biến thôi nhưng chỉ lưu một giá trị trong suốt chương trình, không thể thay đổi được. Nhưng không giống với các ngôn ngữ khác, giá trị của các hằng số trong Ruby là có thể thay đổi được, khi chúng ta thay đổi giá trị hằng thì Ruby không báo lỗi mà chỉ đưa ra mấy dòng cảnh báo.

Tên hằng số được bắt đầu bởi một kí tự viết HOA, thường thì khi đặt tên hằng chúng ta luôn viết hoa toàn bộ các kí tự trong tên.

Name = "Robert"
AGE = 23

Name = "Juliet"

Trong ví dụ trên chúng ta định nghĩa hằng NameAGE, sau đó thay đổi giá trị của Name và Ruby sẽ báo lỗi tương tự như sau.

C:\Project\Ruby>irb constants.rb
constants.rb:4: warning: already initialized constant Name

Giá trị – Literal

Giá trị là các kí tự mô tả một giá trị của một kiểu dữ liệu nào đó, có thể là một con số, một đoạn text… dùng để gán cho các biến. Chúng ta sẽ tìm hiểu về kiểu dữ liệu sau.

age = 29
nationality = "Hungarian"

Trong ví dụ trên thì 29“Hungarian” là giá trị, agenationality là biến.

require 'date'

sng = true
name = "James"
job = nil
weight = 68.5
born = Date.parse("November 12, 1986")

puts "His name is #{name}"

if sng == true
    puts "He is single"
else
    puts "He is in a relationship"
end

puts "His job is #{job}"
puts "He weighs #{weight} kilograms"
puts "He was born in #{born}"

Trong đoạn code trên thì chúng ta có các giá trị có kiểu dữ liệu boolean, kiểu string, kiểu float, kiểu nil – có thể hiểu là kiểu rỗng, kiểu Date.

His name is James
He is single
His job is 
He weighs 68.5 kilograms
He was born in 1986-11-12

Khối lệnh – Block

Khối lệnh là cách để chúng ta gộp nhóm các lênh lại với nhau, bạn sẽ hiểu về khối lệnh nhiều hơn khi thực hành. Khối lệnh trong Ruby được bắt đầu và kết thúc bởi cặp dấu {} hoặc cặp từ khóa do-end.

puts [2, -1, -4, 0].delete_if { |x| x < 0 }
    
[1, 2, 3].each do |e|
    puts e
end

Trong ví dụ trên chúng ta sử dụng cả 2 loại khối lệnh.

Ngoài các câu lệnh tính toán bình thường thì trong lập trình còn có các câu lệnh điều khiển, ví dụ như câu lệnh if, đây là câu lệnh điều kiện, theo sau if là một biểu thức rồi tới một khối lệnh nằm trong cặp từ khóa then-end. Chúng ta sẽ tìm hiểu thêm về các câu lệnh điều kiện sau.

if true then
    puts "Ruby language"
    puts "Ruby script"
end

Sigil

Sigil là các kí tự $@ dùng để khai báo phạm vi hoạt động của biến. Trong đó $ cho biết biến đó là một biến toàn cục, @ cho biết đó là biến instance, @@ là biến class. Chúng ta sẽ tìm hiểu thêm trong bài lập trình hướng đối tượng.

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

Sigil luôn được đặt trước tên biến.

Toán tử

Toán tử là các kí tự thực hiện các hành động nào đó trên một giá trị nào đó.

!    +    -    ~    *    **    /    %
<< >>    &    |    ^
==    ===    !=    <=>    >=    >
<    <=    =    %=    /=    -=
+=    *=    **=    ..    ...    not
and    or    ?:    &&    || 

Chúng ta sẽ tìm hiểu thêm về toán tử sau.

Từ khóa

Từ khóa là các từ ưu tiên trong Ruby, thường dùng làm các câu lệnh thực hiện hành động nào đó, chẳng hạn như in giá trị ra màn hình, thực hiện các công việc lặp đi lặp lại hay thực hiện tính toán. Khi đặt tên biến chúng ta không được đặt tên trùng với từ khóa.

alias    and      BEGIN      begin    break    case
class    def      defined?   do       else     elsif
END      end      ensure     false    for      if
in       module   next       nil      not      or
redo     rescue   retry      return   self     super
then     true     undef      unless   until    when 
while    yield 

 

Ở trên là danh sách các từ khóa có trong Ruby.

Ruby – Giới thiệu về ngôn ngữ Ruby

Chào mừng bạn đến với bài mở đầu series lập trình với ngôn ngữ Ruby. Trong series này, bạn sẽ được học những thành phần chính của ngôn ngữ Ruby, bao gồm biến, biểu thức, tập hợp, luồng điều khiển, biểu thức chính quy và lập trình hướng đối tượng.

Ruby

Ruby logo

Ruby là một ngôn ngữ lập trình động, phản xạ, hướng đối tượng. Tác giả của ngôn ngữ Ruby là một lập trình viên người Nhật tên là Yukihiro Matsumoto. Ruby được giới thiệu lần đầu vào năm 1995.

Ruby hỗ trợ hầu hết các mô hình lập trình truyền thống, bao gồm lập trình hướng đối tượng, lập trình phản xạ, lập trình mệnh lệnh… Ruby được lấy cảm hứng từ Perl, Smalltalk, Effiel và Lisp.

Website chính thức của Ruby có địa chỉ ruby-lang.org.

Trình thông dịch Ruby

Trong series này mình dùng Ruby phiên bản 2.2.4 trên Windows. Bạn có thể tải và cài đặt Ruby cho Windows tại địa chỉ http://rubyinstaller.org/, Khi cài bạn nhớ check lựa chọn cho trình cài đặt tự động gán đường dẫn đến thư mục bin trong biến PATH luôn cho tiện.

Sau khi cài xong, bạn mở Command Prompt (cmd) lên và chạy lệnh irb để mở trình thông dịch Ruby, màn hình cùng với dấu nhắc lệnh của Ruby có dạng như sau:

C:\User\PhoCode> irb
irb(main):001:0> 

Từ đây bạn có thể gõ các lệnh trong Ruby.

irb(main):001:0> puts RUBY_VERSION 
2.2.4 => nil

Ở trên chúng ta chạy lệnh puts, lệnh này sẽ in một đoạn text ra màn hình, ở đây chúng ta in hằng số RUBY_VERSION, hằng số này cho biết phiên bản Ruby mà chúng ta sử dụng.

Viết code Ruby trong file

Ngoài cách chạy Ruby trực tiếp từ trình thông dịch thì chúng ta có thể viết code Ruby trong các file script riêng rồi trình thông dịch sẽ chạy đoạn code trong file đó. Bạn chỉ cần tạo một file text, viết code Ruby trong đó rồi lưu lại với phần mở rộng là .rb.

puts "Hello world"

Đoạn code trên sẽ in chuỗi Hello world ra màn hình.

C:\Project\Ruby>hello.rb 
Hello world

Để chạy file .rb thì bạn mở cmd lên rồi trỏ đến thư mục chứa file này (bằng lệnh cd) sau đó gõ vào tên file là xong.

Tài liệu tham khảo