2012-12-22 35 views
5

Nói rằng tôi có lớp Player và tôi muốn có một phương pháp boolean để kiểm tra xem một cầu thủ bị tấn công:Sử dụng một dấu hỏi trong các phương pháp ruby ​​

class Player 
    attr_accessor :name, :health, :attacked? 

    def initialize(name) 
    @name = name 
    @health = 100 
    @attacked? = false 
    end 
end 

tôi nhận được một lỗi cú pháp:

SyntaxError: (irb):14: syntax error, unexpected '=' 
@attacked? = false 
      ^
     from /usr/bin/irb:12:in `<main>' 

Loại bỏ dấu chấm hỏi từ attacked khắc phục sự cố, nhưng tôi nghĩ rằng sẽ tốt hơn theo quy ước để có attacked? trong mã của tôi. Không phải là vấn đề lớn khi từ bỏ dấu chấm hỏi, nhưng tại sao là các quy ước zero?nil? khi @variables?def methods?= không hợp lệ?

+0

'@ attack' là một biến mẫu, không phải là phương thức. '@attacked = false'; ... 'def tấn công ?; @attacked; end' –

+3

Đoán của tôi là bạn không thể có dấu chấm hỏi như là một phần của tên biến. Đó là chỉ cho các phương pháp. Ngoài ra, tôi không thể nhớ một phương pháp đánh dấu câu hỏi duy nhất với một setter. Họ là tất cả các getters. –

+0

Đó là một điểm tốt. Họ là tất cả các getters. Việc đặt setter với dấu chấm hỏi tạo phương thức "attack? =", Cũng là cú pháp không hợp lệ. Vì vậy, mã của tôi sẽ có tên biến không hợp lệ và tên phương thức không hợp lệ. – rubyuser1357796

Trả lời

11

Lưu ý rằng nếu bạn xóa bỏ dòng gây ra lỗi của bạn (@attacked? = false), bạn vẫn sẽ nhận được một lỗi liên quan đến dấu chấm hỏi:

NameError: invalid attribute name `attacked?' 

Vấn đề là ? không phải là một nhân vật có giá trị trong một tên biến. Lỗi đầu tiên (số SyntaxError mà bạn đang thấy) được gây ra tại thời gian phân tích cú pháp và bị phát hiện ngay lập tức. Lỗi thứ hai được gây ra khi Ruby cố gắng để đánh giá mã và không thể tạo một biến mẫu với một tên có chứa một ký tự không hợp lệ.

Một dấu chấm hỏi ký tự hợp lệ ở phần cuối của một phương pháp tên mặc dù (trên thực tế nó có thể có một phương pháp với một ? bất cứ nơi nào trong tên của nó, nhưng bạn không thể gọi một phương thức như trực tiếp) .

Một cách để đạt được những gì bạn muốn là một cái gì đó như thế này:

class Player 
    attr_accessor :name, :health, :attacked 
    alias :attacked? :attacked 

    def initialize(name) 
    @name = name 
    @health = 100 
    @attacked = false 
    end 
end 

này lá attacked mà không có dấu hỏi, nhưng thêm attacked? như một bí danh.

+0

Cảm ơn! Tôi thậm chí không nghĩ đến việc sử dụng bí danh. – rubyuser1357796

3

Tôi đã gặp phải vấn đề tương tự trước đây và ước rằng tôi có thể tạo biến mẫu bằng dấu chấm hỏi. Nó có vẻ là một trường hợp góc trong ngữ pháp của Ruby. Check this out:

>> 1 ? 2 : 3 
=> 2 
>> 1?2:3 
=> 2 
>> @a = true 
=> true 
>> @a?1:2 
=> 1 
>> a = true 
=> true 
>> a ? 1 : 2 
=> 1 
>> a?1:2 
SyntaxError: (irb):9: syntax error, unexpected ':', expecting $end 

Vì vậy, các biểu tượng ? bị quá tải trong ngữ pháp của Ruby - nó được sử dụng cho các nhà điều hành ternary, như một phần của định danh hợp lệ cho tên phương pháp. Điều này gây ra sự mơ hồ trong trường hợp cuối cùng, trong đó Ruby của lexer dường như cắn tắt các a? như một mã thông báo duy nhất, mà lá nó không thể phân tích phần còn lại của nhà điều hành ternary đúng cách. Với các biến mẫu, điều này không thể xảy ra.

Một lần nữa, tôi đồng ý rằng cho phép các dấu hỏi trong các tên biến cụ thể sẽ rất hữu ích, chắc chắn có giá trị hơn so với việc sử dụng một số thao tác tối nghĩa của toán tử bậc ba không mơ hồ.

Các vấn đề liên quan