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

A.new #still works and calls initialize 

etComment rendre le constructeur de classe privé dans Ruby?

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

ne fonctionne pas tout à fait

Alors, quelle est la bonne façon? Je veux faire new privé et appelez-le via une méthode d'usine.

+0

Je ne sais pas ce que vous voulez est possible, mais même si elle était, en théorie, vous ne pourrait pas l'appeler d'une méthode d'usine parce que ce serait privé. Essayez-vous de créer un singleton? Ou faire un modèle d'inversion de contrôle? – Matt

Répondre

67

Essayez ceci:

class A 
    private_class_method :new 
end 

More on APIDock

+6

Si vous cherchez à implémenter une classe Singleton (la seule raison pour laquelle je peux penser à vouloir un constructeur privé), Ruby le fera pour vous. http://apidock.com/ruby/Singleton – adurity

+2

Et même alors quelqu'un pourrait faire A.send (: new). (BTW, ne devrait pas "classe" être en minuscules?) –

+0

Oui, il devrait. Corrigé maintenant. – adurity

13

Le deuxième morceau de code que vous avez essayé est presque droite. Le problème est private fonctionne dans le contexte de méthodes d'instance au lieu de méthodes de classe.

Pour private ou private :new à travailler, il vous suffit de le forcer à être dans le contexte des méthodes de classe comme ceci:

class A 
    class << self 
    private :new 
    end 
end 

Ou, si vous voulez vraiment redéfinir new et appelez super

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

juste classe niveau des méthodes d'usine peuvent accéder au new privé très bien, mais en essayant de instancier directement en utilisant new échouera parce que new est privé.

+0

Upvoted parce que c'est une manière entièrement valide de faire une méthode privée de classe. Je ne savais pas comment ouvrir les classes il y a six ans. :) –

1

Pour faire la lumière sur l'utilisation, voici un exemple courant de la méthode d'usine:

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 

utiliser ensuite comme

result = A.create('some argument')  

Comme prévu, l'erreur d'exécution se produit dans le cas d'utilisation new directe:

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