2012-07-24 31 views
6

Trong Ruby, sự hiểu biết của tôi là self là bộ nhận ngụ ý cho bất kỳ cuộc gọi phương thức trần nào. Tuy nhiên:Nếu `self` luôn là bộ nhận ngụ ý trong Ruby, tại sao` self.puts` không hoạt động?

~: irb 
>> puts "foo" 
foo 
=> nil 
>> self.puts "foo" 
NoMethodError: private method `puts' called for main:Object 

Điều gì giải thích điều này?

Trong trường hợp đó là bất kỳ sự giúp đỡ:

>> method(:puts).owner 
=> Kernel 
+1

thử 'self.send: puts," foo "'. Bạn có thể nhận được xung quanh phương pháp riêng với gửi. – DGM

Trả lời

8

phương pháp cá nhân không thể có một máy thu

Tôi nghĩ câu trả lời là thế này: cách thực thi phương pháp riêng tư của Ruby là nó không cho phép gọi phương pháp riêng với một máy thu rõ ràng.

Một ví dụ:

class Baker 
    def bake_cake 
    make_batter 
    self.use_oven # will explode: called with explicit receiver 'self' 
    end 

    private 
    def make_batter 
    puts "making batter!" 
    end 

    def use_oven 
    puts "using oven!" 
    end 

end 

b = Baker.new 
b.bake_cake 

Vì có thể có nhận rõ ràng, bạn chắc chắn không thể làm b.use_oven. Và đó là cách thực thi quyền riêng tư của phương thức.

+0

nhưng đặt là phương thức công khai, phương thức (: puts) .owner.public_methods.grep/puts/returns [: puts]. MRI ruby ​​1.93p194 – dfang

+0

xin lỗi , tôi quên tra cứu phương pháp. self.class.ancestors => [Object, Kernel, BasicObject] – dfang

+0

@dfang - có thể nó được phân loại lại là riêng tư bởi một lớp con? –

3

Bạn đúng khi cho rằng self là người nhận ngụ ý khi bạn không xác định một cách rõ ràng. Lý do bạn không được phép làm self.puts là bạn không thể gọi phương thức riêng với người nhận rõ ràng (ngay cả khi người nhận đó là self) và vì thông báo lỗi cho biết, puts là một phương pháp riêng tư.

1

Bạn không thể truy cập các phương pháp riêng bằng ruby ​​sử dụng cú pháp self. hoặc nói chung bằng cách sử dụng bất kỳ bộ thu nào (một cái gì đó ở phía trước .). Điều đó chỉ có thể cho các phương pháp được bảo vệ.

4

Vì đó là định nghĩa về quyền riêng tư trong Ruby: các phương thức riêng tư chỉ có thể được gọi với một trình thu thập ngầm.

Trên thực tế, có một ngoại lệ cho quy tắc này: vì foo = barluôn tạo ra một biến địa phương, bạn được phép gọi setters tin như self.foo = bar, bởi vì nếu không bạn sẽ không thể gọi họ là ở tất cả (không có sử dụng sự phản chiếu).

+1

+1 để hiển thị ngoại lệ. –

+0

Cũng như sử dụng sự phản chiếu, bạn có thể thực hiện 'foo = (bar)' mà không sử dụng 'self'. –

+1

@AndrewGrimm: Không hoạt động, tôi đã thử nó. Nó cũng có nghĩa là nó không hoạt động, bởi vì các dấu ngoặc đơn có thể được sử dụng để nhóm biểu thức, do đó, đó là một phép gán biến cục bộ hợp lệ hoàn toàn. –

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