Các phương thức được bảo vệ và riêng tư trong Rails


81

Khả năng hiển thị phương thức trong Ruby (phương thức công khai, được bảo vệ và riêng tư) đã được giải thích rõ ràng ở những nơi như bài đăng trên blog này . Nhưng trong Ruby on Rails, nó có vẻ hơi khác so với một ứng dụng Ruby thông thường vì cách thiết lập khung công tác. Vì vậy, trong các mô hình Rails, bộ điều khiển, trình trợ giúp, kiểm tra, v.v., khi nào thì / không thích hợp để sử dụng các phương thức được bảo vệ hoặc riêng tư?

Chỉnh sửa : Cảm ơn cho câu trả lời cho đến nay. Tôi hiểu khái niệm được bảo vệ và riêng tư trong Ruby, nhưng tôi đang tìm kiếm thêm lời giải thích về cách điển hình mà các loại khả năng hiển thị đó được sử dụng trong ngữ cảnh của các phần khác nhau của ứng dụng Rails (mô hình, bộ điều khiển, trình trợ giúp, thử nghiệm) . Ví dụ: phương thức bộ điều khiển công khai là phương thức hành động, phương thức được bảo vệ trong bộ điều khiển ứng dụng được sử dụng cho "phương thức trình trợ giúp" cần được truy cập bởi nhiều bộ điều khiển, v.v.

Câu trả lời:


106

Đối với các mô hình, ý tưởng là các phương thức công khai là giao diện công khai của lớp. Các phương thức công khai nhằm mục đích được sử dụng bởi các đối tượng khác, trong khi các phương thức được bảo vệ / riêng tư được ẩn khỏi bên ngoài.

Đây là cách thực hành tương tự như trong các ngôn ngữ hướng đối tượng khác.

Đối với bộ điều khiển và kiểm tra, chỉ cần làm theo ý bạn. Cả bộ điều khiển và lớp kiểm tra chỉ được khởi tạo và được gọi bởi khuôn khổ ( vâng, tôi biết về mặt lý thuyết bạn có thể lấy bộ điều khiển từ chế độ xem, nhưng nếu bạn làm điều đó, dù sao thì cũng có điều gì đó lạ lùng ). Vì không ai trực tiếp tạo ra những thứ đó nên không có gì để "bảo vệ".

Phụ lục / Chỉnh sửa: Đối với bộ điều khiển, bạn nên đánh dấu các phương thức "helper" là được bảo vệ riêng tư và chỉ các hành động tự nó mới được công khai. Khung sẽ không bao giờ định tuyến bất kỳ lệnh gọi HTTP nào đến các hành động / phương thức không công khai, vì vậy các phương thức trợ giúp của bạn phải được bảo vệ theo cách đó.

Đối với người trợ giúp, sẽ không có gì khác biệt nếu một phương thức được bảo vệ hoặc riêng tư, vì chúng luôn được gọi là "trực tiếp".

Tất nhiên, bạn có thể đánh dấu nội dung được bảo vệ trong tất cả những trường hợp đó nếu điều đó khiến bạn dễ hiểu hơn.


" Đối với bộ điều khiển, bạn nên đánh dấu các phương thức" helper "là được bảo vệ và chỉ các hành động đó mới được công khai. " Bạn có khuyên không nên có bất kỳ phương thức riêng tư nào trong bộ điều khiển không? Hay tôi không nên đọc nó theo nghĩa đen?
Dennis

2
Ngày nay tôi chỉ sử dụng private. được bảo vệ và riêng tư được sử dụng thay thế cho nhau ở hầu hết các nơi; nhưng bảo vệ mang đến một hành vi kỳ lạ mà tôi không bao giờ cần trong thế giới thực.
averell

2
Tôi cũng có xu hướng chỉ sử dụng riêng tư. Điều này cũng tuân theo một số nguyên tắc nhất định, chẳng hạn như "Sử dụng chế độ riêng tư thay vì được bảo vệ khi xác định phương thức bộ điều khiển" của Thoughtbot.
Dennis

66

Bạn sử dụng một phương thức riêng tư nếu bạn khôngself muốn ai khác sử dụng một phương thức. Bạn sử dụng một phương thức được bảo vệ nếu bạn muốn một cái gì đó chỉ self and is_a?(self)s có thể gọi.

Một cách sử dụng tốt của protected có thể là nếu bạn có một phương thức khởi tạo "ảo".

class Base
    def initialize()
        set_defaults()
        #other stuff
    end

    protected
    def set_defaults()
        # defaults for this type
        @foo = 7
        calculate_and_set_baz()
    end

    private
    def calculate_and_set_baz()
        @baz = "Something that only base classes have like a file handle or resource"
    end
end

class Derived < Base
    protected
    def set_defaults()
        @foo = 13
    end
end

@foo sẽ có các giá trị khác nhau. và các phiên bản Derived sẽ không có @baz

Cập nhật: Kể từ khi tôi viết bài này, một số thứ đã thay đổi trong Ruby 2.0+ Aaron Patterson có một bài viết xuất sắc http://tenderlovemaking.com/2012/09/07/protected-methods-and-ruby-2-0.html


9
Yêu cách bạn nói self and is_a?(self). Tôi luôn giải thích các phương pháp được bảo vệ có sẵn trong các lớp trẻ em.
Tate Johnson

16
Chú ý ở đây! Đây là một điểm khác biệt quan trọng đối với các ngôn ngữ khác: Các phương thức private cũng có sẵn trong các lớp con. Sự khác biệt duy nhất trong private và protected là bạn có thể gọi các phương thức được bảo vệ bằng "self.set_defaults", trong khi các phương thức private chỉ có thể được gọi là "set_defaults".
averell

Một câu trả lời tốt, nhưng thậm chí không chứa Rails từ đó là điểm của câu hỏi
Bryan Ash

5
Chú ý dấu thời gian Chỉnh sửa câu hỏi của anh ấy. Trong tương lai tôi sẽ xác định một phương pháp riêng để cập nhật câu trả lời của tôi khi họ thay đổi câu hỏi của họ :)
EnabrenTane

Như averell đã nói, lời giải thích này không áp dụng cho ruby. Nơi các phương thức private cũng được hiển thị trong các lớp con.
Miguel

10

Sự khác biệt giữa được bảo vệ và riêng tư là rất nhỏ. Nếu một phương thức được bảo vệ, nó có thể được gọi bởi bất kỳ thể hiện nào của lớp xác định hoặc các lớp con của nó. Nếu một phương thức là private, nó có thể chỉ được gọi trong ngữ cảnh của đối tượng đang gọi --- không bao giờ có thể truy cập trực tiếp vào các phương thức private của đối tượng khác, ngay cả khi đối tượng đó cùng lớp với người gọi. Đối với các phương thức được bảo vệ, chúng có thể truy cập từ các đối tượng cùng lớp (hoặc con).

http://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Classes#Dec Tuyên_Visibility


2
Cảm ơn các liên kết. Nhưng tôi tự hỏi thêm về cách những công việc cụ thể trong Ruby on Rails (phương pháp điều khiển công cộng được coi là phương pháp hành động, phương pháp bảo vệ trong bộ điều khiển ứng dụng có thể được sử dụng bởi các bộ điều khiển khác, vv)
jrdioko

3
Trong trường hợp cuối cùng "các phương thức được bảo vệ trong bộ điều khiển ứng dụng có thể được sử dụng bởi các bộ điều khiển khác", điều này là do các bộ điều khiển khác (nói chung) kế thừa từ ApplicationController nên chúng thực sự sở hữu tất cả các phương thức đó. Họ không truy cập chúng từ application_controller: điều này không bao giờ được khởi tạo. Nó hoàn toàn được sử dụng như cha mẹ để thừa kế.
Max Williams

3

Có vẻ như bạn đã biết rõ về ngữ nghĩa của khả năng hiển thị lớp (công khai / bảo vệ / riêng tư) khi được áp dụng cho các phương thức. Tất cả những gì tôi có thể cung cấp là một bản phác thảo nhanh về cách tôi triển khai nó trong các ứng dụng Rails của mình.

Tôi triển khai các phương thức được bảo vệ trong bộ điều khiển ứng dụng cơ sở để chúng có thể được gọi bởi bất kỳ bộ điều khiển nào thông qua bộ lọc (ví dụ: before_filter: method_foo). Theo cách tương tự, tôi xác định các phương thức được bảo vệ cho các mô hình mà tôi muốn sử dụng trong tất cả chúng trong một mô hình cơ sở mà tất cả chúng đều kế thừa.


2

Mặc dù hành động cần phải là phương thức công khai của bộ điều khiển, nhưng không phải tất cả các phương thức công khai đều nhất thiết phải là hành động. Bạn có thể sử dụng hide_actionnếu bạn đang sử dụng một tuyến bắt tất cả như /:controller/:action/:idhoặc nếu nó bị vô hiệu hóa (mặc định trong Rails 3) thì chỉ các phương thức có các tuyến rõ ràng mới được gọi.

Điều này có thể hữu ích nếu bạn đang chuyển phiên bản bộ điều khiển đến một số thư viện khác như công cụ mẫu lỏng vì bạn có thể cung cấp giao diện công khai thay vì phải sử dụng gửi trong các bộ lọc và thẻ lỏng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.