0

Object Oriented Ruby

Giới Thiệu

Ruby là một ngôn ngữ lập trình hướng đối tượng bởi vậy tất cả mọi thứ trong ruby đều là đối tượng. Ví dụ: strings, numbers, boolean, Class,...

Đối tượng có các phương thức(methods) và các thuộc tính(attributes) biểu diễn dữ liệu. Ví dụ ta có “abc”.length thì “abc” là đối tượng chuỗi với length là phương thức đã được định nghĩa trước và thuộc tính là 3(độ dài của chuỗi abc).

Hướng đối tượng trong Ruby

Định nghĩa đối tượng(Object):

Tất cả mọi thứ trong ruby đều là đối tượng, đối tượng được tạo từ các lớp

Mỗi đối tượng sẽ chứa các thông tin riêng của chúng. và là các instance cho các lớp tương tự nhau.

Ví dụ: ta có 2 đối tượng của lớp String

➜ ~ irb 2.2.3 :001 > "Ruby".class => String 2.2.3 :002 > "Java".class

Trong ví dụ trên, chúng ta đã sử dụng phương thức instance là class để xác định lớp cho mỗi đối tượng. Kết quả trả về đó là lớp String. Như vậy rõ ràng là ta thấy từ chuỗi đến các số chúng đều là các đối tượng thực thể hiệm cho một lớp cụ thể.

Cách khai báo một đối tượng sừ dụng từ khóa new.

ví dụ: khai báo hai đối tượng của lớp People

people1 = People.new people2 = People.new

Định nghĩa lớp(Class):

Ruby định nghĩa các thuộc tình và hành ví của các đối tượng trong các lớp.

Cách để định nghĩa một lớp ta sử dụng từ khóa class. ví dụ:

class class_name # to do end

Theo quy ước thì tên của lớp phải bắt đầu với chữ cái hoa. ví dụ:

class People #to do end

Nếu tên của lớp có nhiều hơn một từ thì bắt đầu mỗi từ nên viết hoa chữ cái đầu. ví dụ:

class MyClass #to do end

Bây giờ nếu chúng ta muốn tạo ra đối tượng của lớp People thì chỉ cần viết: people = People.new

Nói một cách khác là chúng ta đã tạo ra một instance cho lớp People và lưu trữ nó trong biến people. people được gọi là object hay instance của lớp People.

Việc tạo ra một đối tượng hay instance của lớp được gọi là sự khới tạo. Theo ví du trên chúng ta đã tạo ra một đối tượng people từ lớp People.

Điều mà cần chú ý ở đây đó là sau khi chúng ta gọi phương thức new của class thì chúng ta cần lấy được đối tượng trả về.

Giả sử lớp People ở trên chúng ta cần lấy ra đối tượng trả về là tên và tuổi của một người nào đó thì ta sẽ làm như sau:

    2.2.3 :015 > class People
    2.2.3 :016?>   def  initialize(name,age)
    2.2.3 :017?> 	@name = name
    2.2.3 :018?> 	@age = age
    2.2.3 :019?> 	end
    2.2.3 :020?>   end
     => :initialize
    2.2.3 :021 >  p = People.new("avla", 23)
     => #<People:0xb8347dcc @name="avla", @age=23>
    2.2.3 :022 >

Định nghĩa phương thức:

Accessor methods: phương thức này dùng để trả về thuộc tính của đối tượng. Nó còn được gọi là phương thức getter. ví dụ:

    2.2.3 :001 > class People
    2.2.3 :002?>   def initialize(name, age)
    2.2.3 :003?>     @name = name
    2.2.3 :004?>     @age = age
    2.2.3 :005?>   end
    2.2.3 :006?>   # Accessor method
    2.2.3 :007 >   def getName
    2.2.3 :008?>     @name
    2.2.3 :009?>   end
    2.2.3 :010?>   def getAge
    2.2.3 :011?>     @age
    2.2.3 :012?>   end
    2.2.3 :013?> end
     => :getAge
    2.2.3 :014 > people  = People.new("avgl", 25)
     => #<People:0xb99de018 @name="avgl", @age=25>
    2.2.3 :015 > people.getName
     => "avgl"
    2.2.3 :016 > people.getAge
     => 25
    2.2.3 :017 >

Setter methods

phương thức này dùng để thiết lập gía trị cho các biến đối tượng.

ví dụ: khởi tạo gía trị cho các biến ở trên

    2.2.3 :001 > class People
    2.2.3 :002?>   def initialize(name, age)
    2.2.3 :003?>     @name = name
    2.2.3 :004?>     @age = age
    2.2.3 :005?>     end
                   #setter method
    2.2.3 :006?>   def setName(value)
    2.2.3 :007?>     @name = value
    2.2.3 :008?>   end
                   #setter method
    2.2.3 :009?>   def setAge(value)
    2.2.3 :010?>     @age = value
    2.2.3 :011?>   end
    2.2.3 :012?> end
     => :setAge
     #use setter method
    2.2.3 :013 > mai = People.new("Mai", 33)
     => #<People:0xb96a007c @name="Mai", @age=33>
    2.2.3 :014 >   people = People.new("Mai", 33)
     => #<People:0xb968b960 @name="Mai", @age=33>
    2.2.3 :015 > people.setName("Lan")
     => "Lan"
    2.2.3 :016 > people.setAge(30)
     => 30
    2.2.3 :017 > people
      => #<People:0xb968b960 @name="Lan", @age=30>

Instance methods Phương thức này dùng để định nghĩa các phương thức do người dùng xây dụng cho một mục đích nào đó,nó không giới hạn số lượng biến đối tượng giống nhưng phương thức setter và getter, nó được khai báo giống như các phương thức thông thường khác đó là dùng từ khóa def

ví dụ:

    2.2.3 :001 > class People
    2.2.3 :002?>   def initialize(name, age)
    2.2.3 :003?>     @name = name
    2.2.3 :004?>     @age = age
    2.2.3 :005?>   end
    2.2.3 :006?>   def printPeople
    2.2.3 :007?>     puts "#{@name} is #{@age}  years old"
    2.2.3 :008?>   end
    2.2.3 :009?> end
     => :printPeople
    2.2.3 :010 > people = People.new("Mai", 20)
     => #<People:0xb9bf69f4 @name="Mai", @age=20>
    2.2.3 :011 > people.printPeople()
    Mai is 20  years old
     => nil
    2.2.3 :012 >

class methods Đây là một phương thức đặc biệt, chúng ta không cần phải khởi tạo đối tượng để gọi phương thức mà dùng ngay chính lớp đó đề gọi.

ví dụ:

    2.2.3 :001 > class People
    2.2.3 :002?>   def initialize(name, age)
    2.2.3 :003?>     @name = name
    2.2.3 :004?>     @age = age
    2.2.3 :005?>   end
                #class method
    2.2.3 :006?>   def self.printPeople()
    2.2.3 :007?>     puts "#{@name} is #{@age}  years old"
    2.2.3 :008?>   end
    2.2.3 :009?> end
     => :printPeople
    # call clasethod
    2.2.3 :011 > People.printPeople()
    Mai is 20  years old
     => nil
    2.2.3 :012 >
Quyền truy cập phương thức

Ruby cung cấp một số quyền để giới hạn truy cập các phương thức sau cho người sử dụng.

public methods: có thể gọi ở bất kỳ nơi nào. Ruby mặc định sử dụng public method.

private methods: một phương thức được giới hạn sử dụng nó chỉ có thể được gọi ở ngay trong lớp đó mà không thể truy cập được từ bên ngoài lớp đó.

protected methods: cũng là một phương thức được giới hạn giống như phương thức private. Nhưng nó cũng có thể truy xuất ở ngoài lớp với điều kiện lớp đó phải kế thừa lớp có chứa phương thức được gọi.

ví dụ:

    2.2.3 :001 > class People
    2.2.3 :002?>   def initialize(name, age)
    2.2.3 :003?>     @name = name
    2.2.3 :004?>     @age = age
    2.2.3 :005?>   end
    2.2.3 :006?>   def printPeople
    2.2.3 :007?>     puts "#{@name} is #{@age} years old"
    2.2.3 :008?>   end
    2.2.3 :009?>   def printName
    2.2.3 :010?>     puts getName
    2.2.3 :011?>   end

    2.2.3 :012?>   private
    2.2.3 :013?>   def getName
    2.2.3 :014?>     @name
    2.2.3 :015?>   end
    2.2.3 :016?>   def getAge
    2.2.3 :017?>     @age
    2.2.3 :018?>   end

    2.2.3 :019?>   protected
    2.2.3 :022?>   def setName(value)
    2.2.3 :023?>     @name = value
    2.2.3 :024?>   end
    2.2.3 :025?>   def setAge(value)
    2.2.3 :026?>     @age = value
    2.2.3 :027?>   end
    2.2.3 :028?> end
     => :setAge

    2.2.3 :029 > people = People.new("Mai", 20)
     => #<People:0xb91ff20c @name="Mai", @age=20>
    # call public method
    2.2.3 :030 > people.printPeople()
    Mai is 20 years old
     => nil
    2.2.3 :031 > people.printName
    Mai
     => nil
    # call private method
    2.2.3 :032 > people.getName
    NoMethodError: private method `getName' called for #<People:0xb91ff20c @name="Mai",NoMethodError: private method `getName' called for #<People:0xb91ff20c @name="Mai",ethod         =20>
        from (irb):32
        from /usr/local/bin/irb:11:in `<main>'
    # call protected method
    2.2.3 :033 > people.setName("Lan")
    NoMethodError: protected method `setName' called for #<People:0xb91ff20c @name="Mai", @age=20>
        from (irb):33
        from /usr/local/bin/irb:11:in `<main>'

Kế thừa lớp:

Là một trong các khái niệm quan trọng nhất của lập trình hướng đối tượng.

Gỉa sử Lớp A kế thừa từ lớp B thì lớp A là lớp cha hay lớp dẫn xuất( base class or superclass). Và lớp B được gọi là lớp con hay lớp được kế thừa (divered class or sub-class).

Lớp con được kế thừa từ lớp cha nó sẽ thừa kế tất cả những phương thức có từ lớp cha( trừ phương thức private). Chính vì vậy nó giảm thiểu được số lượng lớn các code phải viết lại. Đó chính là một ưu điểm lớn của kế thừa.

Nếu lớp A kết thừa từ lớp B ta sẽ viết nó như sau: class B < A...end

ví dụ: chúng ta tạo một lớp Animal có chứa các phương thức được dùng chung phục vụ cho các lớp con sau này của nó. Sau đó chúng ta tạo ra một lớp Cat cho kế thừa từ lớp Animal.

    2.2.3 :001 > class Animal
    2.2.3 :002?>   def initialize(name, feet)
    2.2.3 :003?>     @name = name
    2.2.3 :004?>     @feet = feet
    2.2.3 :005?>   end
    2.2.3 :006?>   def getName
    2.2.3 :007?>     @name
    2.2.3 :008?>   end
    2.2.3 :009?>   def getFeet
    2.2.3 :010?>     @feet
    2.2.3 :011?>   end
    2.2.3 :012?> end
     => :getFeet

    2.2.3 :020 > class Cat < Animal
    2.2.3 :021?>   def printCat
    2.2.3 :022?>     puts "A #{getName} has #{getFeet} feet"
    2.2.3 :023?>   end
    2.2.3 :024?> end
     => :printCat

    2.2.3 :026 > cat = Cat.new("adidas", 4)
     => #<Cat:0xb88bbe48 @name="adidas", @feet=4>
    2.2.3 :027 > cat.printCat()
    A adidas has 4 feet
     => nil
    2.2.3 :028 > cat.getName
     => "adidas"
    2.2.3 :029 >

Modules:

Là tập hợp các methods, constants được sử dụng trong các lớp khác thông qua mixins. Trong ruby không hỗ trợ đa kế thừa nhưng nó cung cấp một khái niệm khác để hỗ trợ dạng đa kế thừa đó là sử dụng mixins.

Để nhúng một module vào lớp khác sử dụng chúng ta dùng từ khóa include.

Giờ chúng ta có thể tạo ra nhiều lớp mà sử dụng chung một module. Gỉa sử ví dụ ở dưới chúng ta tạo ra một module Animal chứa phương thức say là hành vi tiếng kêu của một số động vật. Sau đó ta tạo ra một số lớp ví dụ Cat, Dog...và nhúng module đó vào trong lớp. chúng ta sẽ làm như sau:

    2.2.3 :001 > module Animal
    2.2.3 :002?>   def say(sound)
    2.2.3 :003?>     puts "#{sound}"
    2.2.3 :004?>   end
    2.2.3 :005?> end
     => :say

    2.2.3 :006 > class Cat
    2.2.3 :007?>   include Animal
    2.2.3 :008?> end
     => Cat

    2.2.3 :010 > class Dog
    2.2.3 :011?>   include Animal
    2.2.3 :012?> end
     => Dog

    2.2.3 :013 > cat = Cat.new
     => #<Cat:0xb9869a48>
    2.2.3 :014 > cat.say("meooooooooo")
    meooooooooo
     => nil
    2.2.3 :015 > dog = Dog.new
     => #<Dog:0xb98538d8>
    2.2.3 :018 > dog.say("gatooooooooo")
    gatooooooooo
     => nil
    2.2.3 :019 >

Kết luận:

Tất cả những gì trình bày ở trên là những thứ mà cần thiết nhất cho việc lập trình hướng đối tượng trong Ruby.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí