Hãy xem qua mã này, thì chúng tôi ?
#bowling.rb
class Bowling
@game_score = 0 # (1)
Tại thời điểm này (1), chúng tôi vẫn còn bên trong lớp Bowling
. Hãy nhớ rằng: các lớp chỉ là các đối tượng giống như bất kỳ lớp nào khác. Vì vậy, tại thời điểm này, bạn đang chỉ định 0
cho biến mẫu @game_score
của đối tượng lớp Bowling
.
def hit(pins)
@game_score = @game_score + pins # (2)
Bây giờ (2), chúng ta đang ở trong một phương pháp dụ của lớp Bowling
. I.e: đây là phương pháp sẽ thuộc về một cá thể của Bowling
. Vì vậy, bây giờ biến cá thể @game_score
thuộc về một cá thể của lớp Bowling
và không thuộc về lớp đó.
Kể từ biến trường hợp này không bao giờ được khởi tạo để bất cứ điều gì, nó sẽ đánh giá để nil
(trong Ruby, biến chưa được khởi tạo luôn luôn đánh giá nil
), vì vậy đây để đánh giá @game_score = nil + pins
và kể từ nil
không có một phương pháp #+
, đây sẽ dẫn đến một ngoại lệ NoMethodError
được nâng lên.
end
def score
@game_score # (3)
Và đây (3), chúng tôi một lần nữa bên trong một phương pháp dụ của lớp Bowling
. Điều này sẽ luôn luôn đánh giá là nil
, vì lý do tôi nêu trên: @game_score
không bao giờ được khởi tạo, do đó nó sẽ đánh giá thành nil
.
end
end
Chúng ta có thể sử dụng khả năng phản xạ của Ruby để có một cái nhìn vào những gì đang xảy ra:
p Bowling.instance_variable_get(:@game_score) # => 0
b = Bowling.new
p b.instance_variable_get(:@game_score) # => nil
Bây giờ chúng ta hãy tiêm một giá trị vào biến Ví dụ:
b.instance_variable_set(:@game_score, 1)
p b.score # => 1
b.hit(3)
p b.score # => 4
Vì vậy, chúng ta thấy rằng tất cả mọi thứ hoạt động như nó cần, chúng ta chỉ cần tìm ra cách để đảm bảo biến cá thể được khởi tạo.
Để làm điều đó, chúng ta cần viết phương thức khởi tạo. Kỳ lạ thay, phương thức khởi tạo thực sự là phương thức cá thể riêng được gọi là initialize
. (Lý do tại sao initialize
là một phương thức thể hiện chứ không phải là một phương thức lớp, thực sự khá đơn giản. Ruby chia tách đối tượng tạo thành hai giai đoạn: cấp phát bộ nhớ và khởi tạo đối tượng. được thực hiện bởi một phương thức dụ được gọi là initialize
. (Các lập trình viên mục tiêu-C sẽ nhận ra điều này.) Lý do tại sao alloc
là một phương thức lớp đơn giản là tại thời điểm này trong thực thi chưa có trường hợp nào. Ví dụ phương pháp là khởi tạo đối tượng rõ ràng là mỗi đối tượng. Như một tiện lợi, có một phương thức lớp nhà máy tiêu chuẩn được gọi là new
gọi cả hai số alloc
và initialize
cho bạn.)
class Bowling
def initialize
@game_score = 0
end
end
Hãy kiểm tra này:
c = Bowling.new
p c.score # => 0
c.hit(2)
p c.score # => 2
BTW: chỉ cần một số lời khuyên nhỏ của Ruby phong cách: thụt đầu dòng là 2 không gian, chứ không phải 1 tab. Và phương pháp hit
của bạn sẽ tự động hơn là @game_score += pins
.
Có điều này theo cách Java, chào mừng trong Ruby: D – khelll