Giải thích tính năng Duck Typing của Ruby dưới lăng kính 4OOP
Ruby vẫn luôn được coi là ngôn ngữ rất hướng đối tượng, vì trong Ruby mọi thứ đều là object. Theo bài 4 tính chất đặc thù của lập trình hướng đối tượng, có thể viết chương trình Ruby để thể hiện 4 tính chất ấy. Tuy nhiên, nếu đã có căn bản Ruby, thì chắc bạn đã để ý là không như những ngôn ngữ ...
Ruby vẫn luôn được coi là ngôn ngữ rất hướng đối tượng, vì trong Ruby mọi thứ đều là object. Theo bài 4 tính chất đặc thù của lập trình hướng đối tượng, có thể viết chương trình Ruby để thể hiện 4 tính chất ấy. Tuy nhiên, nếu đã có căn bản Ruby, thì chắc bạn đã để ý là không như những ngôn ngữ ví dụ như Java, Ruby không có từ khóa để thể hiện một cách tường minh tính trừu tượng (từ khóa trong Java: interface) và đa hình (từ khóa trong Java: override).
Có thể giải thích lí do của việc trên, là Ruby có tính năng gọi là Duck Typing để thay thế.
Ta hãy thử làm bài tập 4OOP để sáng tỏ:
class Animal attr_reader :name def initialize(name) @name = name end def say_hello raise 'Subclasses should implement this method' end end class Cat < Animal def say_hello puts "Meow, my name is #{name}" end end class Dog < Animal def say_hello puts "Woof woof, my name is #{name}" end end class Duck def initialize(name) @name = name end def say_hello puts "Trump, my name is #{name}" end end class Zoo def initialize @animals = [] end def add(animal) @animals << animal end def say_hello_all @animals.each { |a| a.say_hello } end end # Some test z = Zoo.new z.add(Cat.new('Kitty')) z.add(Dog.new('Pluto')) z.add(Duck.new('Donald')) z.say_hello_all
Chạy thử sẽ thấy các con vật chào hỏi ngon lành.
Tuy nhiên, để ý sẽ thấy:
- Duck không thừa kế từ Animal. Trong các ngôn ngữ như Java, ta phải định nghĩa interface có phương thức say_hello, để các con vật trong Zoo có chung interface. Còn trong Ruby thì miễn là Duck có phương thức có cùng tên là ta có thể nhét chung với các Animal khác. Ý tưởng của Duck Typing là: Vịt trắng vịt đen đều là vịt, thậm chí bất kể con gì đi như vịt nói như vịt cũng đều có thể coi là vịt.
- Cat và Dog thừa kế phương thức say_hello, và override lại phương thức say_hello của Animal. Nhưng Ruby không có từ khóa override như các ngôn ngữ như Java để thể hiện tường minh chỗ này. Việc này có lẽ nằm trong ý đồ thiết kế của Ruby, là trung thành với ý tưởng Duck Typing. Bạn cũng có thể bỏ say_hello trong Animal đi mà chương trình vẫn chạy tốt.
Hai phân tích ở trên cho thấy mặc dù Duck Typing làm cho Ruby rất uyển chuyển, nhưng vì Ruby không bắt buộc phải định rõ interface và override, để chương trình rõ ràng để những lập trình viên cùng tham gia viết chương trình có thể làm việc suôn sẻ với nhau, trong chương trình cần phải cẩn thận viết comment những chỗ mang tính trừu tượng và đa hình. Nếu không, chỉ cần chương trình to to một chút và vài người cùng viết, thì mã nguồn sẽ thành đống bùi nhùi lúc nào không hay.