2015-04-20 32 views
13

Trong Ruby, chúng ta gán các giá trị cho các đối tượng với toán tử =.Ruby xử lý nhiệm vụ ngữ nghĩa như thế nào?

Kết hợp điều này với gõ ngầm và chúng tôi thường xuyên nhận được những tình huống như thế này:

myVar= :asymbol 

Dòng trên cả hai tạo ra một đối tượng biểu tượng mới, và liên kết với các đối tượng để tên biến myVar.

Về mặt ngữ nghĩa, cách thực hiện điều này?

Tôi đã có nó đóng vào đầu tôi rằng các nhà điều hành =không cú pháp ma thuật được xây dựng vào thông dịch viên, nhưng thực sự là đường chỉ là cú pháp cho phương pháp object.=(value). Với ý nghĩ này, tôi đoán là khi người phiên dịch thấy chúng tôi đang cố gán giá trị cho một tên biến không xác định, trước tiên nó tạo một đối tượng mới của một số loại đặc biệt, như undefined hoặc null hoặc gì đó, và sau đó chuyển thông báo := cho đối tượng đó với trọng tải là giá trị mà chúng tôi đang cố gắng chỉ định.

Tuy nhiên, gọi .class trên đối tượng không được khởi tạo chỉ cần ném ngoại lệ vì Ruby cho rằng chúng tôi đang cố gắng gọi phương thức (tên của biến mà bạn đang cố gắng đưa vào tồn tại) trên self

> obj.class 
    > NameError: undefined variable or method 'obj' for main:Object 

Vì vậy, theo như tôi có thể nói, tôi không có cách nào để tìm ra điều này bằng thực nghiệm.


Side lưu ý:

Trong trường hợp chuyển nhượng biểu tượng, tôi tin rằng giá trị được gán (AKA giá trị trả về bởi phương pháp object_id đối tượng cụ thể của, AKA giá trị của unsigned long VALUE biến trên C level) là một số đại diện cho một offset trong một bảng ở đâu đó (tôi tin rằng đây là cách Ruby đạt được 'giá trị tức thời' cho các đối tượng ký hiệu).

Trong các trường hợp khác, giá trị có thể là mã hóa trực tiếp của đối tượng hoặc giá trị được gán cho con trỏ tham chiếu đến struct.

Bất kể cách nào Ruby đại diện cho đối tượng và liệu chúng tôi có chỉ định tham chiếu hoặc đối tượng không phải là những gì tôi hỏi ở đây.

câu hỏi khác:

lớp là gì = phương pháp được thừa hưởng từ đâu? Tôi không thể tìm thấy nó trong thông số kỹ thuật cho Object hoặc BasicObject.

+2

Giống như "Không có thìa", không có phương pháp '='. – tadman

+0

Đây có phải là bản sao của câu hỏi này không? http://stackoverflow.com/questions/8345755/object-assignment-in-ruby –

+0

@GeorgeStocker Câu hỏi được tham chiếu là về ** hiệu ứng ** của toán tử '=', trong đó như của tôi là về việc triển khai thực hiện trong Ruby. – LukeP

Trả lời

13

Biến, theo nghĩa kỹ thuật, chỉ là con trỏ đến đối tượng. Không có gì đáng chú ý về điều đó, nhưng một phép gán biến đơn giản cho một đối tượng hiện có không liên quan đến bất kỳ cuộc gọi hoặc tin nhắn nào được gửi đi.

Hãy nhớ rằng các biến chỉ ở đó để các lập trình viên có thể tham chiếu đến các đối tượng theo tên thay vì bởi một số loại định danh nội bộ hoặc vị trí bộ nhớ.Vì vậy, có một chút "ma thuật" ở đây, = là đặc biệt khi thực hiện một nhiệm vụ như có quy tắc cho những gì bạn có thể làm ở bên trái và bên phải của nó.

Cách duy nhất bạn có thể gửi tin nhắn cho một thứ gì đó, đó là thực hiện cuộc gọi phương thức, là nếu bạn đã xác định nó theo cách mà trình biên dịch hiểu được. x = 1 là đủ, nó có nghĩa là x đề cập đến các Fixnum trong câu hỏi.

Lưu ý rằng các thông dịch viên Ruby sẽ cần phải xác định xem x đề cập đến một cuộc gọi biến hoặc phương pháp, như x= có thể là một phương pháp đó là xác định trên bối cảnh đối tượng mà điều này được đánh giá.

Ví dụ:

class Example 
    def x=(value) 
    @x = value 
    end 

    def test 
    # Equivalent to send(:x=, 1) because x= is a method 
    x = 1 

    # Is a variable definition because y= is not a method 
    y = 2 

    # Is always a method call because self is referenced. 
    self.x = 3 
    end 
end 

# Is a variable definition because x= is not defined in this context 
x = 4 

Nếu không có phương pháp x= cho đối tượng của bạn, x được tự động coi là một biến.

Bạn không thể có thông báo := vì điều đó có nghĩa là bạn có thể thay thế một đối tượng bằng một đối tượng khác, một thứ không được phép. Khi một đối tượng được tạo ra, nó không thể thay đổi một cách kỳ diệu kiểu. Để làm được điều đó, bạn cần tạo một thể hiện mới của một đối tượng khác. Các biến chỉ xuất hiện để thay đổi các loại, nhưng trên thực tế, chúng chỉ kết thúc trỏ đến các đối tượng khác nhau.

Vì vậy, trong ngắn hạn, không có cuộc gọi phương thức := nhưng có thể có các phương pháp đặc biệt như :x= hoạt động trong các trường hợp rất cụ thể.

+0

Câu trả lời tốt! ... –

+1

Một điều khác: 'value =" newval "' luôn được coi là một biến (chứ không phải là một phương thức) trừ khi có một người nhận rõ ràng. Vì vậy, nếu bối cảnh của bạn đã định nghĩa ': value =', thì bạn phải gọi 'self.value = arg' để truy cập phương thức đó một cách rõ ràng. – acsmith

+0

@acsmith Điều này trở thành một vấn đề khi phương pháp được giới thiệu sau khi mã được biên dịch. Điểm tốt. – tadman

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