07/09/2018, 16:59

Singleton Method And Singleton Class In Ruby

Vậy là một tuần mới cũng đã đến. Mình xin chúc tất cả các bạn có một tuần làm việc thật vui vẻ nhé (yeah). Hôm nay mình sẽ giới thiệu với các bạn bài viết trong chủ đề Ruby quen thuộc: Singleton method và singleton class trong Ruby. Như các bạn cũng đã biết, Ruby là một ngôn ngữ lập trình ...

ruby-mini-logo.png

Vậy là một tuần mới cũng đã đến. Mình xin chúc tất cả các bạn có một tuần làm việc thật vui vẻ nhé (yeah).

Hôm nay mình sẽ giới thiệu với các bạn bài viết trong chủ đề Ruby quen thuộc: Singleton method và singleton class trong Ruby.

Như các bạn cũng đã biết, Ruby là một ngôn ngữ lập trình tương đối dễ viết, dễ đọc. Tuy nhiên, có không ít những khái niệm nếu không nắm rõ sẽ rất dễ gây ra nhầm lẫn, sử dụng sai,....

Trong bài viết này, mình sẽ cố gắng làm rõ các khái niệm liên quan đến Singleton method và Singleton class trong Ruby. Hy vọng sẽ giúp cung cấp được một vài điều bổ ích cho các bạn (dance2).

Chúng ta bắt đầu nào.

1. Singleton Method

Để có thể giải thích đơn giản và dễ hiểu, chúng ta cùng xem ví dụ sau về cách khai báo cũng như cách sử dụng Singleton method sau đây nhé:

class Hoge
end

h = Hoge.new
p h.respond_to?(:hi) #=> false

# Singleton method là method chỉ được định nghĩa riêng cho 1 object cụ thể.
def h.hi
 "hi!"
end

# method "hi" chỉ được khai báo sử dụng cho object "h"
p h.respond_to?(:hi) # => true
p h.hi # => "hi!"
p h.singleton_methods # => [:hi]

# Những instance khác của class Hoge sẽ không sử dụng được method "hi"
h2 = Hoge.new
p h2.respond_to?(:hi) # => false

Như ở ví dụ trên, chúng ta đã khai báo method "hi", sử dụng riêng cho object h là 1 instance của class Hoge. Method "hi" ở đây được gọi là một singleton method.

2. Singleton Class

Một trong những nguyên lý hướng đối tượng cơ bản của Ruby là việc các method được khai báo trong Class, và những method này có thể được sử dụng bởi tất cả các instance của Class đó.

Vậy sự xuất hiện của khái niệm singleton method chẳng phải là bất thường sao (?).

Để tương thích với sự xuất hiện bất thường của khái niệm singleton method trên, khái niệm Singleton Class ra đời. "Tất cả các object đều có một Singleton Class của riêng nó". Với khái niệm này, chúng ta có thể hiểu singleton method của một object là method được định nghĩa trong Singleton Class của chính object đó.

Chúng ta có thể gọi Singleton Class của một object bằng method singleton_class như sau:

obj = Object.new
p obj.singleton_class #=> #<Class:#<Object:0x007fea6187f318>>

Ở ví dụ trên, ta có thể thấy instance obj của Class Object có Singleton Class của nó là #<Class:#<Object:0x007fea6187f318>>.

Đối với nil hay false, chúng ta cũng có thể gọi đến method singleton_class, method này sẽ trả về Singleton Class của nil và false tương ứng là NilClass và FalseClass.

p nil.singleton_class   #=> NilClass
p false.singleton_class #=> FalseClass

Trên đây chúng ta đã được tìm hiểu về khái niệm của singleton method và singleton class. Tiếp theo chúng ta sẽ đi sâu hơn một chút, tìm hiểu về cách sử dụng Singleton Class cũng như sự liên kết giữa Singleton Class và Class method nhé (dance3)

3. Sử dụng Singleton Class

Như đã đề cập ở trên, mỗi object đều có một Singleton Class của riêng mình.

Vậy khi ta muốn mở rộng Singleton Class của một object (ví dụ như thêm instance method chẳng hạn) thì ta phải làm thế nào? Bạn sẽ có câu trả lời ngay sau đây thôi :D.

Để access được vào Singleton Class của object obj, chúng ta dùng cú pháp như sau:

obj = Object.new
p obj.singleton_class #=> #<Class:#<Object:0x007f8cbb9bf0d8>>

class << obj
  p self #=> #<Class:#<Object:0x007f8cbb9bf0d8>>

  def hi
    "hi"
  end
end

# gọi singleton method đã được thêm vào
p obj.hi #=> hi

Việc khai báo method "hi" phía trên tương đương với việc chúng ta khai báo một singleton method bằng các đã làm ở ví dụ đầu bài viết:

def obj.hi
  "hi"
end

4. Singleton Class của class

Chắc các bạn đều đã được nghe đến câu: "Mọi thứ trong Ruby đều là Object".

Các Class cũng vậy, String, Array, Integer, ... hay class Hoge chúng ta định nghĩa ở trên đều là instance của class Class.

Chúng ta có thể kiểm tra bằng cách sau:

class Hoge; end

p String.instance_of? Class #=> true

p String.class  #=> Class
p Array.class   #=> Class
p Integer.class #=> Class
p Hoge.class    #=> Class

Class cũng là một Object, vì vậy mỗi class cũng có Singleton Class của riêng mình. Do đó, chúng ta cũng có thể thêm vào các singleton method cho chúng.

p String.class #=> Class
p String.singleton_class #=> #<Class:String>

class << String
  p self #=> #<Class:String>

  def shout(str)
    str + '!!!'
  end
end

p String.shout('hello') #=> hello!!!

Ở ví dụ trên, về mặt bản chất chúng ta gọi singleton method String.shout, tuy nhiên ta cũng có thể nhìn thấy nó tương đương với việc gọi một class method (method shout của class String).
Trên thực tế, class method là một loại singleton method (yeah).

Chúng ta có thể thấy rõ hơn qua ví dụ dưới đây:

class Knife
  def cut(sth)
    sth.to_s.split(').join('|')
  end

  # Khai báo một class method (1)
  def self.hoge
    'hoge'
  end

  p self # => Knife

  # Khai báo class method (2)
  def Knife.fuga
    'fuga'
  end

  # Khai báo class method (3)
  class << self
    # self ở đây sẽ là Singleton của object Knife
    p self #=> #<Class:Knife>
    def piyo
      'piyo'
    end
  end
end

knife = Knife.new
p knife.cut("tomato") #=> "t|o|m|a|t|o"

p Knife.hoge #=> "hoge"
p Knife.fuga #=> "fuga"
p Knife.piyo #=> "piyo"

5. Kết luận

Trên đây là những khái niệm cơ bản về singleton method, singleton class cũng như các sử dụng và mở rộng chúng.

Ruby thực sự là một ngôn ngữ đẹp, dễ đọc, dễ viết, nhưng để có thể làm chủ được nó là cả một chặng đường dài.

Hy vọng các bạn đã tìm được cho mình một vài điều bổ ích qua bài viết này, để trang bị thêm cho hành trang chinh phục người đẹp Ruby =))

0