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

A.new #still works and calls initialize 

Rubyでクラスコンストラクタをprivateにするには?

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

は全く

を動作しませんので、正しい方法は何ですか?私はnewをプライベートにして、ファクトリメソッドで呼びたいと思っています。あなたがしようとしたコードの2番目のチャンクはほとんど右である

class A 
    private_class_method :new 
end 

More on APIDock

+0

私はあなたが望むものは可能ですが、理論的には、プライベートであるためファクトリメソッドから呼び出すことはできません。シングルトンを作成しようとしていますか?あるいは制御パターンを反転させるか? – Matt

答えて

67

はこれを試してみてください。問題は、privateがクラスメソッドの代わりにインスタンスメソッドのコンテキストで動作していることです。

privateまたはprivate :new作業を取得するには、ちょうどこのようなクラスメソッドのコンテキストであることを強制する必要があります:あなたは本当にnewを再定義し、呼び出したい場合は、

class A 
    class << self 
    private :new 
    end 
end 

するか、super

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

クラスレベルファクトリメソッドはうまくプライベートnewにアクセスできますが、newがプライベートであるため、newを使用して直接インスタンス化しようとすると、失敗します。ここで、使用にいくつかの光を当てること

+6

あなたがシングルトンクラスを実装しようとしている場合(プライベートコンストラクタがほしいと思う唯一の理由です)、Rubyがそれを行います。 http://apidock.com/ruby/Singleton – adurity

+2

さらに誰かがA.send(:new)を実行することもできます。 (BTW、 "クラス"は小文字ではないはずです) –

+0

はいそうです。今修正されました。 – adurity

13

+0

これは、クラスプライベートメソッドを作成するために完全に有効な方法であるため、上書きされます。私は6年前に授業を開くことについて知らなかった。 :) –

1

は、ファクトリメソッドの一般的な例である:

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 

そして予想されるように、ランタイムエラーが場合に発生

result = A.create('some argument')  

として使用します直接newの使用:

a = A.new('this leads to the error') 
関連する問題