Ruby in little view
1. Ruby
Ruby được phát triển bởi một người Nhật bản tên là Yukihiro Matsumoto. Là một ngôn ngữ lập trình động kiểu thông dịch, Ruby khá phức tạp về mặt cú pháp nhưng lại đem lại nhiều ấn tượng về các thư viện gốc với các giao diện lập trình ứng dụng khá mạnh mẽ.
Ruby được nhiều người đánh giá là giống với Lisp (L), Smalltalk(L) và Perl nhưng sử dụng cấu trúc cú pháp của Java và C.
2. Inside Ruby
Cũng như các ngôn ngữ lập trình khác, Ruby cũng có các quy định về cú pháp, kiểu dữ liệu, các cấu trúc điều khiển luồng, các toán tử…
Ruby Fundamentals
a. Cấu trúc một chương trình Ruby
Là một dạng của ngôn ngữ lập trình thế hệ thứ 3 (3GL: 3rd Generation Language), một trương trình Ruby bao gồm các thư viện liên kết và các đoạn mã được phân chia theo khối ( code block). Bên cạnh đó với đặc điểm là ngôn ngữ thông dịch được viết theo dạng script, chương trình không cần hàm main mà được thực thi theo thứ tự các dòng mã.
Một chương trình có thể lưu trong nhiều tập tin mã nguồn khác nhau và được sử dụng lại thông qua cấu trúc lệnh : require hoặc path
Khai báo trong Ruby không quá phức tạp như các ngôn ngữ khác vì không yêu cầu xác định kiểu dữ liệu trong cấu trúc khai báo.
Ví dụ:
myString = 'This is my String'
myInt = 5’
b. Các dạng dữ liệu và đối tượng
Ruby là một ngôn ngữ hướng đối tượng 100%. Ở đây các thành phần dữ liệu từ số, ký tự, mảng…. đều được xây dựng trên cơ sở các lớp.
Số:
Cấu trúc phân cấp dữ liệu dạng số trong Ruby:
Các dạng dữ liệu kiểu số được xây dựng từ lớp Numeric. Kiểu số nguyên : Integer có hai dạng là Fixnum với độ dài 31 bits và Bignum có độ dài tùy ý. Kiểu số thực được thể hiện qua lớp Float. Bên cạnh đó một số kiểu dữ liệu khác không có sẵn nhưng được định nghĩa trong các thư viện chuẩn của Ruby.
Ký tự
String là lớp dùng để thể hiện chuỗi ký tự. Khác với Java String trong Ruby là “mutable” . String trong Ruby có thể được khai báo trong dấu ngoặc đơn hoặc ngoặc kép. Với dạng chuỗi được đặt trong dấu nháy đơn ‘’ thì ký tự \ chỉ có ý nghĩa khi sau nó là ký tự \ hoặc ‘. Bên cạnh đó chuỗi trong nháy đơn được viết xuống dòng thì nó sẽ được hiển thị thành nhiều dòng tương ứng.
Với dạng chuối trong dấu nháy kép “” thì nhiều ký tự đặc biệt được hỗ trợ, ví dụ như \n, \t như trong java. Bên cạnh đó chuối trong dấu nháy kép còn có thể hiện thị kết quả của biểu thức trong nó thông qua ký tự #. Ví dụ :
string = "So Pi co gia tri la #{Math::PI}"
puts string
Sẽ hiển thị kết quả là: So Pi co gia tri la 3.14159265358979
Mảng
Mảng có thể khai báo trực tiếp hoặc thông qua đối tượng Array.
arr = [1,2,3,4,5,6]
arr = Array.new
Cách đánh chỉ số mảng trong Ruby cũng tương tự như trong java tức là từ 0 đến số phần tử -1. Tuy nhiên có một điều khác biệt ở chố các chỉ số <0.>
Một điểm đặc biệt nữa là trong Ruby, việc sắp xếp các thành phần mảng khá linh hoạt và mềm dẻo. Ta có thể khai báo mảng một chiều gồm các phần tử đơn: arr = [1,2,3,4,5,6]. Hoặc mảng lồng: arr = [[1,2],[3,4,5,6],[7,8,9]]. Hoặc mảng được trích xuất subArr = arr[0,2] #subArr = [[1,2],[3,4,5,6]].
Các mảng có thể tương tác với nhau thông qua các toán tử như +,-,*…
Với phép + ta có thể cộng hai mảng với nhau: ar= [1,2,3] +[4] # ar=[1,2,3,4]
Với phép trừ các phần tử mảng ở mảng trừ sẽ loại bỏ các phần tử có trong mảng bị trừ.
ar= [1,2,3] -[2] # ar=[1,3]
Với phép nhân, ta có thể nhân một mảng với một số và kết quả cho ta số phần tử mảng được lặp lại theo giá trị được nhân: ar= [1,2,3]*2 # ar= [1,2,3,1,2,3]
Các mảng có thể đính thêm phần tử với phép toán <<: ar= [1,2,3]<<4 # ar= [1,2,3,4]
Và các phép so sánh: |, &. Với | các giá trị trùng lặp của hai mảng sẽ được bỏ đi ( kể cả các phần tử trùng lặp trong 1 mảng. ar = [1,2,2,4,3,4] | [] # ar[1,2,4,3]. Trong khi đó với phép toán & các phần tử trùng nhau được giữ lại ( và không lặp). ar = [1,2,2,4,3,4] & [4,4] # ar[4]
c. Toán tử trong Ruby
Bảng dưới đây mô tả các toán tử trong Ruby với thứ tự ưu tiên từ cao xuống thấp
N: Số toán hạng
A: Thứ tự thực hiện (L: trái sang phải, R: phải sang trái)
d. Các cấu trúc điều khiển
d1. Các cấu trúc điều kiện
if
if <<điều kiện>>
<
end
<
if-else
if <<điều kiện>>
<
else
<
end
elsif
if <<điều kiện>>
<
elsif<<điều kiện>>
<
elsif<<điều kiện>>
<
end
unless
unless <<điều kiện>>
<
end
unless cũng có thể được sử dụng với else như trường hợp của if.
case
Case trong Ruby không lằng nhằng như trong java ( quên break là cả một vấn đề rồi). Ở đây có thể sử dụng cấu trúc elseif để đưa ra khối điều khiển giống như trong khối điều khiển case, tuy nhiên cú pháp case vấn thường được sử dụng nhiều hơn.
case
when <
when <
when <
end
Chú ý là ở đây nếu có nhiều hơn một điều kiện đúng thì hành động của điều kiện đầu tiên sẽ được thực hiện
Ví dụ
x=1
a=case
when x>0 then
puts "x is 1"
puts "hehe"
when x==2 then puts "x is 2"
when x<3 then "three"
end
puts a
Kết quả sẽ là
x is 1
hehe
nil
* cấu trúc ?: trong Ruby giống như trong java nhưng được mô tả như cấu trúc if với ? là then và : là else J
d2. Các cấu trúc lặp và liệt kê
while
while < < End | begin < while < |
util
util <<condition>> do <<actions>> End | begin <<actions>> end util <<conditions>> |
for
for <<variables>> in <<collection>> do
<<actions>>
end
Cấu trúc liệt kê
+ Với đối tượng số
upto/downto
0.upto(9){|s| print s}
times
10.times{|s| print s}
step
0.step(9,1){|x| print x}
+ Với Hash, Array, Range
each
(1..9).each{|s| print s}
Result: 123456789
collect
result = (2..4).collect{|s| s*s*s}
puts result
Result:
8
27
64
select
positive = [1,-2,3,4,-9].select{|s| s>0}
puts positive
Result:
1
3
4
reject
negative = [1,-2,3,4,-9].reject{|s| s>0}
puts negative
Result:
-2
-9
d3. Ngoại lệ
Ngoại lệ và cách điều khiển ngoại lệ trong Ruby có phần khá giống với Java với raise ~throw và try-catch~begin-rescue-end
Một số ví dụ
Ruby | Java |
def factorialOf(n) raise ArgumentError, "Wrong argument" if n <0 factorial =1 1.upto(n){|x| factorial*=x} return factorial end begin factorialOf(-1) rescue ArgumentError=>ex puts ex.message end | public static long factorialOf(int n) throws Exception{ if(n<0)>throw new Exception("Wrong argument"); long factorial=1; for(int i=0;i return factorial; } public static void main(String args[]){ try{ System.out.println(factorialOf(-1)); }catch(Exception ex){ System.out.println(ex.toString()); } } |
Wrong argument | java.lang.Exception: Wrong argument |
d4. Các từ khóa điều khiển
Ruby cũng cung cấp một số từ khóa hỗ trợ điều khiển cấu trúc chương trình như: return, break, next, redo, retry, throw/catch
d5. Blocks
Trong quá trình sử dụng các cấu trúc liệt kê, chúng ta thường thấy một nhóm các câu lệnh nằm trong cặp ngoặc nhọn hoặc trong long khối begin/end. Người ta gọi đó là block. Thông thường block bao giờ cũng được thực hiện sau lời gọi hàm
Ví dụ:
10.downto(0){|x| print x}
Ở đây khối |x| print x được thực hiện sau lời gọi hàm và đó là block. Theo quy ước thì với với block trong phạm vi một dòng ta nên dùng ngoặc nhọn còn với block có nhiều dòng ta nên sử dụng do .. end
Chú ý là trong block, giá trị trả về được thông qua câu lệnh next chứ không phải là return (chỉ trả về giá trị cho hàm đóng).
e. Methods, procs, lamdas và closures
Phương thức có cú pháp như sau:
def <
Ví dụ:
def squareRootOf(n,loop)
ini = n/2
loop.times {ini = (n/ini + ini)/2}
return ini
end
Một điểm đặc biệt ở đây là nhiều giá trị có thể đồng thời được trả về trong một phương thức. Các giá trị trả về sẽ được tập hợp trong một mảng.
Ví dụ:
def multiValuesReturn()
return 1, 'hello', 1.4
end
arr = multiValuesReturn
arr.each {|x| print x}
procs và lambdas
procs và lambdas là hai cách thức để đưa blocks vào trong đối tượng. Tùy thuộc vào cách mà đối tượng được tạo ra ta sẽ có procs hay lambdas.
Tạo procs
def createProcs(&p)
p
end
exp = createProcs{|x,y| x**y}
Hoặc
exp = Proc.new{|x,y| x**y}
Gọi procs
puts exp.call(2,3)
Tạo lambdas
incre = lambda{|x| x+1}
hoặc
incre= ->(x){x+1} # ruby version 1.9
hoặc
incre=->(x;step=2){x+step} # Một tham số x và biến nội bộ step
Gọi lambdas
puts incre.call(2)
Closures
Closures là một khái niệm chỉ một hàm sử dụng một biến giới hạn. Thông thường closures dùng để nói đến hàm lồng. Ở đó hàm bên trong sử dụng biến được khai báo bởi hàm chứa nó. Ở Ruby, khái niệm này thường được thể hiện bởi các khối lambdas hoặc procs.
Ví dụ
def mainFunction(n,m)
lambda{|x| x*n/m}
end
myLambda = mainFunction(2,4)
puts myLambda.call(2)
Kết quả ở đây là 1
f. Lớp và modules
Là một ngôn ngữ hướng đối tượng, khái niệm lớp là thành phần cơ bản trong Ruby. Lớp được khai báo như sau:
class <<name_of_class>>
<<body_of_class>>
end
Khới tạo class
<<name_of_class>>.new
Hàm khởi tạo trong lớp. ( giống như hàm tạo và khởi tạo giá trị trong java)
def initialize(<<var1>>,<<var2>>)
<<khới tạo các giá trị>>
end
Đối với các hàm việc xác định khả năng truy cập được thông qua các từ khóa public , private, protected giống như Java. Tuy nhiên ở Java chúng ta có thêm default và được coi như mặc định trong khai báo còn ở đây public được coi là mặc định trong khai báo. Public cho phép các hàm được truy nhập từ bất kỳ đâu trong khi private chỉ cho các hàm được truy nhập từ các thành phần khác trong lớp đó và các lớp con của nó, protected giống private chỉ khác ở chỗ các hàm protected có thể được gọi bởi các thực thể của chính lớp đó hoặc với sefl.
class Test
private
def myTest()
puts "test"
end
protected
def proTest()
puts "pro"
end
public
def testTest()
theTest = Test.new
theTest.proTest()
end
def testPrivate()
theTest = Test.new
theTest.myTest()
end
end
a = Test.new
a.testTest()# =>pro
a.testPrivate()#=> error in red as below
Kết quả:
pro
HelloWorld.rb:20:in `testPrivate': private method `myTest' called for #
from HelloWorld.rb:28
Bên cạnh đó ở Ruby các biến trong lớp đều được đặt là private, trong khi các hằng số đều là public.
Thừa kế trong Ruby
Là ngôn ngữ hướng đối tượng nên Ruby có đầy đủ các tính chất như tính đa hình, đóng gói… và kế thừa
class Parent
def printOut
puts "This is Parent class"
end
end
class Child <>
def printOut
puts "This is Child Class"
end
end
Modules
Modules là nhóm các thành phần hàm, biến, hằng số và chạy độc lập
module MyModule
def MyModule.intro
puts "This is the intro of modul"
end
def MyModule.sayHello
puts "Hello"
end
end
class MyClass
include(MyModule)
def sayHello
MyModule.sayHello
end
end
myClass = MyClass.new
myClass::sayHello
Một chương trình có thế gồm nhiều file, và với ngôn ngữ script như Ruby thì việc phân chia chương trình thành các file chứa các module khác nhau.Các file này sau đó có thể được sử dụng thông qua lời gọi require hoặc load trong chương trình chính.
3. Phát triển ứng dụng Ruby với Eclipse
Mặc dù được phát triển từ hơn một thập kỷ trước ở Nhật và được đánh giá là một trong những ngôn ngữ lập trình hướng đối tượng khá mạnh nhưng Ruby dường như vẫn được ít người biết đến. Lý do chính là chưa có môi trường phát triển phù hợp cho việc xây dựng các ứng dụng lớn đòi hỏi nhiều tính năng hỗ trợ.
Ruby Development Tools là mội trường phát triển cho các ứng dụng Ruy. RDT có ưu điểm là mã nguồn mở và có khả năng tích hợp với Eclipse. Với RDT, việc xây dựng các ứng dụng trên nền ngôn ngữ Ruby sẽ dễ dàng hơn nhờ các tính năng hỗ trợ soạn thảo, thông dịch và debug.
Tích hợp RDT
- Mở Eclipse
- Chọn Help---Software Update---Find and Install
- Chọn Search for new features install --- New Remote Site
- Nhập vào: http://updatesite.rubypeople.org/release
- OK --- Finish
Bắt đầu một ứng dụng Ruby
- File----New ---- Ruby Project
Tạo class
Chuột phải vào project và chọn New---Ruby Class
Tuy nhiên, là ngôn ngữ thông dịch nên việc khai báo class có thể thực hiện tùy ý trong chương
trình.
Chạy Ruby
Chuột phải vào đoạn mã và chọn Run As—Ruby Application
Debuging
Trước hết đặt vào các Break Point, chuột phải vào mã nguồn, chọn Debug As, Ruby Application
Testing
Nếu như với java, nhiều người quen thuộc vơi JUnit thì ở Ruby Unit Test là test framework được sử dụng khá thông dụng
Không có nhận xét nào:
Đăng nhận xét