Phương thức (hàm) (Bài trước)
(Bài tiếp) Tính kế thừa

Lập trình hướng đối tượng, các lớp trong Ruby

Ruby là ngôn ngữ hướng đối tượng hoàn toàn, mọi thứ trong Ruby đều là đối tượng, từ các con số đơn giản, chuỗi ... Các đối tượng là những đơn vị độc lập, nó xác định cụ thể chức năng, có vai trò trong thế thới thực. Như quả cam là một đối tượng, tương tự như thế cái cốc là một đối tượng, mỗi đối tượng là duy nhất, bạn có thể có hai trái cam có vẻ giống nhau nhưng nó là hai thực thể khác nhau.

Để tạo ra các đối tượng ta cần sử dụng các lớp, lớp nó định nghĩa trong nó gồm có dữ liệu và các ứng xử (phương thức).

Bạn có thể hình dùng các lớp như là những mô tả tổng quát về đối tượng sẽ được tạo ra về tính chất và khả năng của nó (ví dụ, một lớp Car có thể có màu, đời, khả năng di chuyển ...).

Một lớp khai báo bắt đầu bằng từ khóa class theo sau là tên của lớp, tên này bao giờ cũng bắt đầu bằng chữ in hoa. Kết thúc khai báo tên lớp với từ khóa end, ví dụ

class Person
end

Ví dụ trên tạo ra một lớp rỗng tên là Person, tiếp theo bạn cần định nghĩa các biến và các phương thức (gọi là thành viên) của lớp.

Phương thức khởi tạo

Có một phương thức đặc biệt được gọi tự động mỗi khi đối tượng từ lớp được tạo ra, gọi là phương thức khởi tạo có tên là initialize, nó được định nghĩa giống như các phương thức khác trong lớp, mục đích có hàm tạo là để khởi tạo các biến, dữ liệu của đối tượng được sinh ra.

class Person
    def initialize
        puts "Hi there"
    end
end

Tạo đối tượng

Sau khi có định nghĩa lớp, có phương thức khởi tạo thì có thể khởi tạo ra một đối thược là một thực thể cụ thể của lớp, khởi tạo bằng phương thức new, là phương thức định nghĩa trước trong Ruby

Ví dụ sau tạo ra hai đối tượng p1 và p2

class Person
  def initialize
    puts "Hi there"
  end
end

p1 = Person.new
p2 = Person.new

# Output:
# "Hi there"
# "Hi there"

Các đối tượng còn gọi là thực thể (instance) của lớp.

Biến instance trong lớp

Các biến khai báo trong lớp là biến thực thể, mỗi đối tượng từ lớp tạo ra có một phiên bản copy của các biến này. Các biến thực thể này khai báo với tiền tối @, ví dụ @name, có thể khởi tạo các biến này thông qua phương thức khởi tạo.

class Person
    def initialize(name)
        @name = name
    end
end

p = Person.new("XuanThuLab")

Tất nhiên là một lớp có thể có nhiều biến instance

class Animal
  @age = 0
  def initialize(name, age)
    @name = name
    @age = age
  end
end

ob = Animal.new("Jacky", 3)

Phương thức instance trong lớp

Một đối tượng ở thế giới thực nó đều có các ứng xử, phản ứng ví dụ ô tô di chuyển, điện thoại đổ chuông ... Tương tự bạn định nghĩa các ứng xử trong lớp bằng cách khai báo các phương thức trong lớp, các phương thức này truy cập thông qua đối tượng cụ thể (thực thể tạo ra từ tên lớp).

class Dog
  def bark # định nghĩa phương thức instance
    puts "Woof!"
  end
end
 

Lớp trên định nghĩa có trong nó một phương thức tên bark, khi thi hành nó thì in ra dòng chữ Woof.

Để gọi phương thức của đối tượng dùng cú pháp dấu chấm

d = Dog.new
d.bark              # Gọi phương thức của đối tượng

Phương thức getter/setter

Để truy cập các biến của đối tượng ta cần xây dựng các phương thức để truy cập đọc biến và phương thức để gán giá trị vào biến gọi là setter và getter. Cách thực hành tốt là đặt tên phương thức getter và setter trùng với tên biến tương tác, ví dụ để tương tác với biến @name tạo ra phương thức getter là name và phương thức setter là name=

class Product
    def initialize(name)
      @name = name
    end
    # Định nghĩa getter để đọc biến @name
    def name
      @name
    end
    # Định nghĩa setter để cập nhật biến
    def name=(name)
      @name = name
    end
  end

  p = Product.new("Iphone")

  p.name = "Laptop"        # Gọi setter
  puts p.name              # Gọi getter
  # Laptop

Phương thức lớp, biến lớp, hằng số trong lớp

Phương thức lớp

Trong định nghĩa lớp có thể khai báo những phương thức mà có thể truy cập thông qua tên lớp (không cần đối tượng lớp tạo ra, giống phương thức tĩnh trong C#) gọi là phương thức lớp. Để tạo ra loại phương thức này dùng từ khóa self

class Xinchao
    # Phương thức lớp có tên hello
    def self.hello
        puts "Xin chào"
    end
end

# Gọi phương thức lớp qua tên lớp
Xinchao.hello

Biến lớp

Tương tự có thể tạo ra các biến thuộc về lớp (không thuộc về đối tượng cụ thể) có thể truy cập thông qua tên lớp. Để khao báo biến lớp name dùng ký hiệu @@name

class Product
    @@total = 10
    def self.total
        @@total
    end
    def self.total=(total)
        @@total = total
    end
end

Product.total = 100
puts Product.total

Hằng số trong lớp

Có thể tạo ra các hằng số trong lớp bằng khai báo tên với ký tự đầu tiên viết In hoa. Ví dụ PI, để truy cập hằng dùng tên tên lớp và ký hiệu ::

class Calc
  PI = 3.14
end

puts Calc::PI

Phương thức to_s

Phương thức to_s là xây dựng sẵn trong Ruby, mọi đối tượng đều có phương thức này, phương thức này được gọi tự động khi cần lấy thông tin đối tượng (chuỗi thông tin).

class Product
end

p = Product.new
puts p
#In ra #<Product:0x00007fcbed81db78>

Khi gọi puts p thì phương thức to_s của p tự động gọi trả về chuỗi #<Product:0x00007fcbed81db78>

Bạn có thể định nghĩa lại to_s để lớp không sử dụng hàm xây dựng mặc định

class Product
  @name = ''
  def initialize
    @name = 'Iphone'
  end

  def to_s
    "Sản phẩm #{@name}"
  end
end

p = Product.new
puts p
# Sản phẩm Iphone

Thuộc tính trong lớp - accessor

Trong Ruby có cơ chế để tự động sinh ra các getter/setter cho các biến instance, đó là sử dụng phương thứcattr_accessor, khai báo sử dụng từ khóa attr_accessor rồi liệt kê các các thuộc biến dạng :name, cách nhau bởi ,. Các hàm setter/getter dạng này nếu truy cập từ trong lớp thì dùng seft.

class Person
  attr_accessor :name, :age                     # khai báo này tự động có các phương thức name,name=, age, age=
  def initialize(name, age)
    @name = name
    @age = age
  end
  def change(n, a)
    self.name = n                               # truy cập accessor setter trong lớp thì cần dùng self.
    self.age = a
  end
  def show_info
    puts "#{self.name} is #{self.age}"          # truy cập accessor getter trong lớp thì cần dùng self.
  end
end

p = Person.new("David", 28)
p.change("Bob", 42)
p.show_info
puts p.age                                      # Truy cập getter accessory

Đăng ký theo dõi ủng hộ kênh
Phương thức (hàm) (Bài trước)
(Bài tiếp) Tính kế thừa