Class Definitions trong ruby
Bài đăng này đã không được cập nhật trong 3 năm
Trước khi đi vào nội dung chính có một chú ý nhỏ với bạn đó là mọi thứ bạn học về class cũng có thể áp dụng cho modules.
Một số các khái niệm liên quan như self
, accesstor_chain
, reserver
các bạn có thể tham khảo ở đây Method và blog trong ruby
I. Khái quát về class
Một ví dụ về class
2.1.5 :004 > class Viblo
2.1.5 :005?> "Hi"
2.1.5 :006?> "Welcome to Viblo"
2.1.5 :007?> end
=> "Welcome to Viblo"
-
Nhìn vào ví dụ trên ta cũng có thể thấy được class nó cũng giống như block hay method sẽ return ở câu lệnh cuối cùng.
-
Bản thân class cũng tuân theo quy tắc của current object
self
. -
Class chỉ đơn giản object, và tên của class là hằng số(constant)
1. current class
- Bất cứ khi nào bạn mở một class với từ khóa
class
(hay module với từ khóamodule
) thì class này sẽ trở thành current class.
ví dụ:
class Viblo
#current clas là Viblo
def topics
end
end
- current class giống với
self
- class definition - Tất cả các method thông thường được định nghĩa bên trong sẽ trở thành instance method của
current class
(như trên thì ta có instance methodtopics
)
2. class_eval()
-
Nó được sử dụng để add method vào class, nó là một method trong Module và nó khá giống với
instance_eval()
. Ngoài ra thìclass_eval()
nó còn có một tên khác nữa làmodule_eval()
. -
Sự khác biệt giữa
instance_eval()
vàclass_eval()
ở đây là gì? Câu trả lời làinstance_eval()
chỉ thay đổiself
cònclass_eval()
thay đổi cảself
và current class. DO thay đổi class nên nó rất hữu ích trong việc mở class và làm một số việc trong đó thay vì bạn phát viết mở class + class name. -
Nếu bạn muốn thay đổi object mà nó không phải là class thì sử dụng
instance_eval()
nhưng nếu bạn muốn mở một class và định nghĩa một phương thức bên trong đó thìclass_eval()
là sự lựa chọn đúng đắn.ví dụ:
def add_method_to(class_name)
class_name.class_eval do
def topics
"many topics here"
end
end
end
Từ ví dụ trên bạn có thể thấy class_eval() cho phép ta add method vào trong bất kỳ một class nào mà không biết tên trước.
3. Class instance variables
- Trong class tất cả các instance variable đều thuộc về curent object
self
(self lúc này là class). Instance variable ucar class thì khác với instance variable object của class.
class Viblo
@language = "Vietnamese"
def self.show
@language
end
def change
@language = "Japanese"
end
def show
@language
end
end
2.1.5 :040 > Viblo.show
=> "Vietnamese"
2.1.5 :041 > Viblo.new.show
=> nil
2.1.5 :042 >
Từ ví dụ trên bạn thấy dường như @language
ở đây nằm trong scope khác nhau và nó là hai biến không bị ảnh hưởng lẫn nhau.
2.1.5 :045 > vib = Viblo.new
=> #<Viblo:0x00000001abfc88>
2.1.5 :046 > vib.show
=> nil
2.1.5 :047 > vib.change
=> "Japanese"
2.1.5 :048 > vib.show
=> "Japanese"
2.1.5 :049 > Viblo.show
=> "Vietnamese"
Có nói như sau: `@language` được định nghĩa với object `vib` và nó là một instance variable của object `vib`.
Còn biến `@language` định nghĩa ngay bên dưới từ khóa *class Viblo* là một instance variable của class `Viblo` (Class instance variable).
Tóm lại: Class instance variable chỉ có thể truy cập bởi chính bản thân class, các instance của class hoặc subclass không thể truy cập được.
Vậy để thay đổi được biến language đó ở mọi nơi trong class thì làm thế nào. ta sẽ đi đến phần tiếp theo
4. Class variables
- Class variable khác với class instance variable bởi chúng cho thể được truy cập bởi bản thân class, subclass, hay các instance method thông thường. Chúng được định nghĩa bắt đầu với tiền tố
@@
(@@language chẳng hạn)
class Viblo
@@language = "Vietnamese"
def self.show
@@language
end
def change
@@language = "Japanese"
end
def show
@@language
end
end
2.1.5 :080 > obj = Viblo.new
=> #<Viblo:0x00000001ca7de8>
2.1.5 :081 > obj.show
=> "Vietnamese"
2.1.5 :082 > Viblo.show
=> "Vietnamese"
2.1.5 :083 > obj.change
=> "Japanese"
2.1.5 :084 > Viblo.show
=> "Japanese"
2.1.5 :085 >
II. Singleton Methods
1. Singleton Methods là gì?
- Là việc add một method vào trong một object.
2.1.5 :085 > str = "welcome to viblo"
=> "welcome to viblo"
2.1.5 :086 > def str.up_case
2.1.5 :087?> self.upcase
2.1.5 :088?> end
=> :up_case
2.1.5 :089 > str
=> "welcome to viblo"
2.1.5 :090 > str.up_case
=> "WELCOME TO VIBLO"
Như ví dụ trên thì ta không quan tâm đến str là object str
là của class nào mà vẫn có thể định nghĩa cho nó một phương thức, nhưng chỉ với object str
có phương thức đó còn các object khác thì không.
2.1.5 :091 > str_new = "Ruby on Rails"
=> "Ruby on Rails"
2.1.5 :092 > str_new.up_case
NoMethodError: undefined method `up_case' for "Ruby on Rails":String
2. Class methods
- Có một vài cách để định nghĩa một class method
class Viblo
def self.class_method_1
end
def Viblo.class_method_2
end
class << self
def class_method_3
end
end
end
- Cách thứ 3 là cách mà mọi người thường hay sử dụng nhất. giờ hay xem cách khai báo của
class_method_1
vàclass_method_2
và so sánh với ví dụng trướcstr.up_case
. Cách khai báo là hoàn toàn giống nhau, và cách gọi cũng vậy
str.up_case
Viblo.class_method_1
- Thực ra thì class method chính là Signeleton method của class.
Và đề tìm hiểu sâu hơn nữa về singleton method ta sẽ đi đến phần tiếp theo
**4. Eigenclasses **
- Singleton method của class không sống trong object cũng không sống trong class vậy nó sống ở đâu? Có một class mà bạn không thể thấy nó được, nó là một class đặt biệt, một class ẩn và nó có tên là Eigenclass của object. Và đó là nơi mà Singleton method cư trú .
- Eigenclass chỉ có duy nhất một instance .
class Object
def eigenclass
class << self
self
end
end
end
2.1.5 :110 > "viblo".eigenclass
=> #<Class:#<String:0x00000001cf6600>>
- Nếu trong một object có eigenclass ruby sẽ tìm kiếm phương thức bên trong eigenclass trước thay vì tìm các method thông thường. Nếu như ruby không tìm thấy phương thức trong eigenclass thì nó sẽ tìm theo
ancestors chain
** Eigenclasses và kế thừa**
Dấu # sẽ được đánh dấu là eigenclass (#D là eigenclass của class D)
Nhìn vào hình vẽ trên cho ta thấy: superclass của Eigenclass #obj là class D, superclass của eigenclass #D là eigenclass #C (eigenclass của class C).
- Ta có kết luận sau: superclass của eigenclass của một object là class của object đó. superclass của eigenclass của một class là eigenclass của superclass của class.
5. Module và các vấn đề
- Khi một class include một module nó sẽ lấy tất các instance_method của module, không lấy class method của module
module MyModule
def self.my_method
'hello'
end
end
class MyClass
include MyModule
end
2.1.5 :125 > MyClass.my_method
NoMethodError: undefined method `my_method' for MyClass:Class
Để include được ta phải dùng đến Eigenclass
module MyModule
def my_method
'hello'
end
end
class MyClass
class << self
include MyModule
end
end
2.1.5 :136 > MyClass.my_method
=> "hello"
- my_method lúc này trở thành instance method của eigenclass của MyClass. lúc này nó cũng là một class method của Myclass. công nghệ này gọi là Class Extension
All rights reserved