Viblo Learning
+2

Một số vấn đề về kế thừa trong ruby

Như chúng ta đã biết, ruby là một ngôn ngữ hướng đối tượng, mọi thứ trong ruby gần như đều là object. Hôm nay mình xin đi vào 1 vấn đề trong OOP của ruby, cũng là 1 vấn đề rất quan trọng trong hướng đối tượng, đó là kế thừa - cụ thể là đa kế thừa trong ruby.

Trước khi đi vào vấn đề chính, mình xin nhắc lại một chút định nghĩa về kế thừa, kế thừa là:

  • Phát triển lớp mới từ lớp đã có
  • Lớp mới được tạo thành là lớp con, lớp được kế thừa là lớp cha
  • Có tính tái sử dụng bằng cách kế thừa các thành phần dữ liệu và hành vi của lớp cha.

Dễ dàng liên tưởng thực tế, 1 cha có thể có nhiều con, và 1 con thì chỉ có duy nhất 1 cha. Và vì thế 1 lớp chỉ được kế thừa duy nhất từ 1 lớp khác - đơn kế thừa. Nhưng trong một số thiết kế riêng, cần phải sử đa kế thừa để giải quyết, cũng như làm cho mô hình được sáng hơn. Vậy làm thế nào để có thể sử dụng đa kế thừa? Ruby sinh ra 1 định nghĩa đó là module giúp ta giải quyết được vấn đề này.

Module A
  def methodA
    puts "This is method of module A"
  end
end

Module B
  def methodB
    puts "This is method of module B"
  end
end

Class C
include A
include B
end

c = C.new
c.methodA
#This is method of module A
c.methodB
#This is method of module B

Và cũng chính từ đây nảy sinh ra vấn đề mà chúng ta cần xem xét.

Vấn đề 1:

Giả sử A và B cùng có 1 phương thức tên là methodX. Vậy khi C include A,B và gọi methodX thì methodX sẽ được gọi từ module nào?

Và ruby xử lí bằng cách, sẽ lấy từ module được include gần nhất tính từ trên xuống dưới.

Module A
  def methodX
    puts "This is method of module A"
  end
end

Module B
  def methodX
    puts "This is method of module B"
  end
end

Class C
include A
include B
end

c = C.new
c.methodX
#This is method of module B

Vấn đề 2:

Nếu cả module A,B cùng include một module C - chưa phương thức methodC. Sau đó class D cùng include module A,B. Và khi D gọi methodC thì nó sẽ hiểu lấy từ A hay B??

module C
  def methodC
    puts "This is method of module C"
  end
end

module A
  include C
end

module B
  include C
end

class D
  include A
  include B
end

d = D.new
d.methodC
#This is method of module C"

Về mặt kết quả, thì không có vấn đề gì, nhưng khi nghĩ về mặt kế thừa, sẽ cảm thấy bất ổn. 😄. Và ruby cũng giải quyết đó là lấy theo module gần nhất tính từ trên xuống.

Bài viết của mình xin dừng tại đây. Có thể có nhiều sai xót, mong mọi người chia sẻ. Thanks!


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.