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

A.new #still works and calls initialize 

y¿Cómo hacer que el constructor de la clase sea privado en Ruby?

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

no funciona por completo

¿Cuál es la forma correcta? Quiero hacer que new sea privado y llamarlo a través de un método de fábrica.

+0

no estoy seguro de lo que quiere es posible, pero incluso si lo era, en teoría, se no sería capaz de llamarlo desde un método de fábrica porque sería privado. ¿Estás tratando de crear un singleton? ¿O hacer un patrón de inversión de control? – Matt

Respuesta

67

Prueba esto:

class A 
    private_class_method :new 
end 

More on APIDock

+6

En caso de que esté buscando implementar una clase Singleton (la única razón por la que puedo pensar en querer un constructor privado), Ruby lo hará por usted. http://apidock.com/ruby/Singleton – adurity

+2

E incluso entonces alguien podría hacer A.send (: nuevo). (Por cierto, ¿no debería la "clase" ser minúscula?) –

+0

Sí, debería. Corregido ahora. – adurity

13

El segundo trozo de código que ha intentado es casi correcto. El problema es private está operando en el contexto de métodos de instancia en lugar de métodos de clase.

Para obtener private o private :new para trabajar, sólo tiene que forzarlo a estar en el contexto de los métodos de clase de esta manera:

class A 
    class << self 
    private :new 
    end 
end 

O, si realmente desea volver a definir new y llame super

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

métodos de fábrica de nivel de clase pueden acceder a la new privada muy bien, pero tratando de crear instancias directamente utilizando newnew fallará porque es privado.

+0

Votación máxima porque esta es una forma totalmente válida de hacer que el método privado sea de clase. No sabía acerca de abrir clases de clases hace seis años. :) –

1

para arrojar alguna luz sobre el uso, aquí es un ejemplo común del método de fábrica:

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 

luego usarlo como

result = A.create('some argument')  

Como era de esperar, el error de tiempo de ejecución se produce en el caso de directa new uso:

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