2009-10-14 2 views
44
class A 
private 
    def initialize 
    puts "wtf?" 
    end 
end 

A.new #still works and calls initialize 

Làm thế nào để làm cho hàm tạo lớp riêng tư trong Ruby?

class A 
private 
    def self.new 
    super.new 
    end 
end 

không hoạt động hoàn toàn

Vì vậy, một cách chính xác là những gì? Tôi muốn đặt new riêng tư và gọi nó qua phương thức nhà máy.

+0

Tôi không chắc chắn những gì bạn muốn là có thể, nhưng ngay cả khi đó là, về lý thuyết, bạn sẽ không thể gọi nó từ phương thức nhà máy vì nó sẽ là riêng tư. Bạn đang cố gắng để tạo ra một singleton? Hoặc làm một mô hình đảo ngược kiểm soát? – Matt

Trả lời

67

Hãy thử điều này:

class A 
    private_class_method :new 
end 

More on APIDock

+6

Trong trường hợp bạn đang tìm cách để thực hiện một lớp Singleton (lý do duy nhất tôi có thể nghĩ đến việc muốn một nhà xây dựng riêng), Ruby sẽ làm điều đó cho bạn. http://apidock.com/ruby/Singleton – adurity

+2

Và thậm chí sau đó ai đó có thể làm A.send (: mới). (BTW, không nên "lớp" là trường hợp thấp hơn?) –

+0

Có nó nên. Đã sửa ngay. – adurity

13

Các đoạn thứ hai của mã bạn đã thử gần như ngay. Vấn đề là private đang hoạt động trong ngữ cảnh của các phương thức thể hiện thay vì các phương thức lớp.

Để có được private hoặc private :new để làm việc, bạn chỉ cần buộc nó là trong bối cảnh các phương pháp lớp học như thế này:

class A 
    class << self 
    private :new 
    end 
end 

Hoặc, nếu bạn thực sự muốn xác định lại new và gọi super

class A 
    class << self 
    private 
    def new(*args) 
     super(*args) 
     # additional code here 
    end 
    end 
end 

Phương thức nhà máy cấp lớp có thể truy cập riêng tư new tốt, nhưng cố gắng khởi tạo trực tiếp bằng cách sử dụng new sẽ không thành công vì new là riêng tư.

+0

Được thăng hạng vì đây là cách hoàn toàn hợp lệ để tạo phương thức riêng tư cho lớp học. Tôi không biết về việc mở lớp học của lớp sáu năm trước. :) –

1

Để làm sáng tỏ về việc sử dụng, đây là một ví dụ phổ biến của phương pháp nhà máy:

class A 
    def initialize(argument) 
    # some initialize logic 
    end 

    # mark A.new constructor as private 
    private_class_method :new 

    # add a class level method that can return another type 
    # (not exactly, but close to `static` keyword in other languages) 
    def self.create(my_argument) 
    # some logic 
    # e.g. return an error object for invalid arguments 
    return Result.error('bad argument') if(bad?(my_argument)) 

    # create new instance by calling private :new method 
    instance = new(my_argument) 
    Result.new(instance) 
    end 
end 

Sau đó, sử dụng nó như

result = A.create('some argument')  

Đúng như dự đoán, lỗi runtime xảy ra trong trường hợp của trực tiếp new cách sử dụng:

a = A.new('this leads to the error')